Mercurial > hg > toybox
comparison toys/pending/nbd_client.c @ 893:6f5fed66c722
Some work I did over the weekend on nbd_client, not sure where I left off...
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 07 May 2013 22:03:31 -0500 |
parents | 84959a5529e8 |
children | e11684e3bbc5 |
comparison
equal
deleted
inserted
replaced
892:f2a8f8981c83 | 893:6f5fed66c722 |
---|---|
4 * | 4 * |
5 * Copyright 2010 Rob Landley <rob@landley.net> | 5 * Copyright 2010 Rob Landley <rob@landley.net> |
6 * | 6 * |
7 * Not in SUSv4. | 7 * Not in SUSv4. |
8 | 8 |
9 USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3", TOYFLAG_USR|TOYFLAG_BIN)) | 9 USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3ns", TOYFLAG_USR|TOYFLAG_BIN)) |
10 | 10 |
11 config NBD_CLIENT | 11 config NBD_CLIENT |
12 bool "nbd-client" | 12 bool "nbd-client" |
13 default n | 13 default n |
14 help | 14 help |
15 usage: nbd-client [-ns] HOST PORT DEVICE | |
16 | |
17 -n Do not fork into background | |
18 -s nbd swap support (lock server into memory) | |
19 */ | |
20 | |
21 /* | |
15 Usage: nbd-client [-sSpn] [-b BLKSZ] [-t SECS] [-N name] HOST PORT DEVICE | 22 Usage: nbd-client [-sSpn] [-b BLKSZ] [-t SECS] [-N name] HOST PORT DEVICE |
16 | 23 |
17 -b block size | 24 -b block size |
18 -t timeout in seconds | 25 -t timeout in seconds |
19 -s swap | |
20 -S sdp | 26 -S sdp |
21 -p persist | 27 -p persist |
22 -n nofork | 28 -n nofork |
23 -d DEVICE | 29 -d DEVICE |
24 -c DEVICE | 30 -c DEVICE |
25 */ | 31 */ |
26 | 32 |
27 #define FOR_nbd_client | 33 #define FOR_nbd_client |
28 #include "toys.h" | 34 #include "toys.h" |
29 | 35 #include "toynet.h" |
30 //#include <errno.h> | |
31 //#include <fcntl.h> | |
32 //#include <limits.h> | |
33 #include <netdb.h> | |
34 //#include <stdint.h> | |
35 //#include <stdio.h> | |
36 //#include <stdlib.h> | |
37 //#include <string.h> | |
38 //#include <unistd.h> | |
39 #include <netinet/tcp.h> | |
40 //#include <sys/ioctl.h> | |
41 //#include <sys/mount.h> | |
42 //#include <sys/types.h> | |
43 //#include <sys/socket.h> | |
44 //#include <sys/stat.h> | |
45 | 36 |
46 #define NBD_SET_SOCK _IO(0xab, 0) | 37 #define NBD_SET_SOCK _IO(0xab, 0) |
47 #define NBD_SET_BLKSIZE _IO(0xab, 1) | 38 #define NBD_SET_BLKSIZE _IO(0xab, 1) |
48 #define NBD_SET_SIZE _IO(0xab, 2) | 39 #define NBD_SET_SIZE _IO(0xab, 2) |
49 #define NBD_DO_IT _IO(0xab, 3) | 40 #define NBD_DO_IT _IO(0xab, 3) |
59 int sock = -1, nbd, flags; | 50 int sock = -1, nbd, flags; |
60 unsigned long timeout = 0; | 51 unsigned long timeout = 0; |
61 struct addrinfo *addr, *p; | 52 struct addrinfo *addr, *p; |
62 char *host=toys.optargs[0], *port=toys.optargs[1], *device=toys.optargs[2]; | 53 char *host=toys.optargs[0], *port=toys.optargs[1], *device=toys.optargs[2]; |
63 uint64_t devsize; | 54 uint64_t devsize; |
64 char data[124]; | |
65 | |
66 // Parse command line stuff (just a stub now) | |
67 | |
68 // Make sure the /dev/nbd exists. | |
69 | |
70 if (0>(nbd = open(device, O_RDWR))) { | |
71 fprintf(stderr, "Can't open '%s'\n", device); | |
72 exit(1); | |
73 } | |
74 | 55 |
75 // Repeat until spanked | 56 // Repeat until spanked |
76 | 57 |
58 nbd = xopen(device, O_RDWR); | |
77 for (;;) { | 59 for (;;) { |
78 int temp; | 60 int temp; |
79 struct addrinfo hints; | 61 struct addrinfo hints; |
80 | 62 |
81 // Find and connect to server | 63 // Find and connect to server |
85 hints.ai_socktype = SOCK_STREAM; | 67 hints.ai_socktype = SOCK_STREAM; |
86 if (getaddrinfo(host, port, &hints, &addr)) addr = 0; | 68 if (getaddrinfo(host, port, &hints, &addr)) addr = 0; |
87 for (p = addr; p; p = p->ai_next) { | 69 for (p = addr; p; p = p->ai_next) { |
88 sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); | 70 sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); |
89 if (-1 != connect(sock, p->ai_addr, p->ai_addrlen)) break; | 71 if (-1 != connect(sock, p->ai_addr, p->ai_addrlen)) break; |
72 close(sock); | |
90 } | 73 } |
91 freeaddrinfo(addr); | 74 freeaddrinfo(addr); |
92 | 75 |
93 if (!p) { | 76 if (!p) perror_exit("%s:%s", host, port); |
94 fprintf(stderr, "Can't connect '%s' port '%s'\n", host, port); | |
95 exit(1); | |
96 } | |
97 | 77 |
98 temp = 1; | 78 temp = 1; |
99 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &temp, sizeof(int)); | 79 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &temp, sizeof(int)); |
100 | 80 |
101 // Log on to the server. (Todo: one big 8+8+8+4+124=152 read) | 81 // Read login data |
102 | 82 |
103 if (read(sock, data, 8) != 8 || memcmp(data, "NBDMAGIC", 8) | 83 xreadall(sock, toybuf, 152); |
104 || read(sock, &devsize, 8) != 8 | 84 if (memcmp(toybuf, "NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53", 16)) |
105 || SWAP_BE64(devsize) != 0x420281861253LL | 85 error_exit("bad login %s:%s", host, port); |
106 || read(sock, &devsize, 8) != 8 || read(sock, &flags, 4) != 4 | 86 devsize = SWAP_BE64(*(uint64_t *)(toybuf+16)); |
107 || read(sock, data, 124) != 124) | 87 flags = SWAP_BE32(*(int *)(toybuf+24)); |
108 { | |
109 fprintf(stderr, "Login fail\n"); | |
110 exit(1); | |
111 } | |
112 devsize = SWAP_BE64(devsize); | |
113 flags = SWAP_BE32(flags); | |
114 | 88 |
115 // Set 4k block size. Everything uses that these days. | 89 // Set 4k block size. Everything uses that these days. |
116 ioctl(nbd, NBD_SET_BLKSIZE, 4096); | 90 ioctl(nbd, NBD_SET_BLKSIZE, 4096); |
117 ioctl(nbd, NBD_SET_SIZE_BLOCKS, devsize/4096); | 91 ioctl(nbd, NBD_SET_SIZE_BLOCKS, devsize/4096); |
118 ioctl(nbd, NBD_CLEAR_SOCK); | 92 ioctl(nbd, NBD_CLEAR_SOCK); |
119 | 93 |
120 // If the sucker was exported read only, respect that locally. | 94 // If the sucker was exported read only, respect that locally. |
121 temp = (flags & 2) ? 1 : 0; | 95 temp = (flags & 2) ? 1 : 0; |
122 if (ioctl(nbd, BLKROSET, &temp)<0) { | 96 xioctl(nbd, BLKROSET, &temp); |
123 fprintf(stderr, "Login fail\n"); | |
124 exit(1); | |
125 } | |
126 | 97 |
127 if (timeout && ioctl(nbd, NBD_SET_TIMEOUT, timeout)<0) break; | 98 if (timeout && ioctl(nbd, NBD_SET_TIMEOUT, timeout)<0) break; |
128 if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) break; | 99 if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) break; |
129 | 100 |
130 // if (swap) mlockall(MCL_CURRENT|MCL_FUTURE); | 101 if (toys.optflags & FLAG_s) mlockall(MCL_CURRENT|MCL_FUTURE); |
131 | 102 |
132 // Open the device to force reread of the partition table. | 103 // Open the device to force reread of the partition table. |
133 if (!fork()) { | 104 if ((toys.optflags & FLAG_n) || !fork()) { |
134 char *s = strrchr(device, '/'); | 105 char *s = strrchr(device, '/'); |
135 sprintf(data, "/sys/block/%.32s/pid", s ? s+1 : device); | 106 int i; |
136 // Is it up yet? | 107 |
137 for (;;) { | 108 sprintf(toybuf, "/sys/block/%.32s/pid", s ? s+1 : device); |
138 temp = open(data, O_RDONLY); | 109 // Is it up yet? (Give it 10 seconds.) |
139 if (temp == -1) sleep(1); | 110 for (i=0; i<100; i++) { |
111 temp = open(toybuf, O_RDONLY); | |
112 if (temp == -1) msleep(100); | |
140 else { | 113 else { |
141 close(temp); | 114 close(temp); |
142 break; | 115 break; |
143 } | 116 } |
144 } | 117 } |
145 close(open(device, O_RDONLY)); | 118 close(open(device, O_RDONLY)); |
146 exit(0); | 119 if (!(toys.optflags & FLAG_n)) exit(0); |
147 } | 120 } |
148 | 121 |
149 // Daemonize here. | 122 // Daemonize here. |
150 | 123 |
151 daemon(0,0); | 124 daemon(0,0); |
152 | 125 |
153 // Process NBD requests until further notice. | 126 // Process NBD requests until further notice. |
154 | 127 |
155 if (ioctl(nbd, NBD_DO_IT)>=0 || errno==EBADR) break; | 128 if (ioctl(nbd, NBD_DO_IT)>=0 || errno==EBADR) break; |
156 close(sock); | 129 close(sock); |
157 close(nbd); | |
158 } | 130 } |
131 close(nbd); | |
159 | 132 |
160 // Flush queue and exit. | 133 // Flush queue and exit. |
161 | 134 |
162 ioctl(nbd, NBD_CLEAR_QUEUE); | 135 ioctl(nbd, NBD_CLEAR_QUEUE); |
163 ioctl(nbd, NBD_CLEAR_SOCK); | 136 ioctl(nbd, NBD_CLEAR_SOCK); |
164 | |
165 exit(0); | |
166 } | 137 } |