|
Network Block Device @PACKAGE_VERSION@
|
00001 /* 00002 * Open connection for network block device 00003 * 00004 * Copyright 1997,1998 Pavel Machek, distribute under GPL 00005 * <pavel@atrey.karlin.mff.cuni.cz> 00006 * Copyright (c) 2002 - 2011 Wouter Verhelst <w@uter.be> 00007 * 00008 * Version 1.0 - 64bit issues should be fixed, now 00009 * Version 1.1 - added bs (blocksize) option (Alexey Guzeev, aga@permonline.ru) 00010 * Version 1.2 - I added new option '-d' to send the disconnect request 00011 * Version 2.0 - Version synchronised with server 00012 * Version 2.1 - Check for disconnection before INIT_PASSWD is received 00013 * to make errormsg a bit more helpful in case the server can't 00014 * open the exported file. 00015 * 16/03/2010 - Add IPv6 support. 00016 * Kitt Tientanopajai <kitt@kitty.in.th> 00017 * Neutron Soutmun <neo.neutron@gmail.com> 00018 * Suriya Soutmun <darksolar@gmail.com> 00019 */ 00020 00021 #include "config.h" 00022 #include "lfs.h" 00023 00024 #include <sys/ioctl.h> 00025 #include <sys/socket.h> 00026 #include <sys/types.h> 00027 #include <unistd.h> 00028 #include <netinet/tcp.h> 00029 #include <netinet/in.h> 00030 #include <netdb.h> 00031 #include "netdb-compat.h" 00032 #include <stdio.h> 00033 #include <fcntl.h> 00034 #include <syslog.h> 00035 #include <stdlib.h> 00036 #include <sys/mount.h> 00037 #include <sys/mman.h> 00038 #include <signal.h> 00039 #include <errno.h> 00040 #include <getopt.h> 00041 #include <stdarg.h> 00042 00043 #include <linux/ioctl.h> 00044 #define MY_NAME "nbd_client" 00045 #include "cliserv.h" 00046 00047 #ifdef WITH_SDP 00048 #include <sdp_inet.h> 00049 #endif 00050 00051 #define NBDC_DO_LIST 1 00052 00053 int check_conn(char* devname, int do_print) { 00054 char buf[256]; 00055 char* p; 00056 int fd; 00057 int len; 00058 00059 if( (p=strrchr(devname, '/')) ) { 00060 devname=p+1; 00061 } 00062 if((p=strchr(devname, 'p'))) { 00063 /* We can't do checks on partitions. */ 00064 *p='\0'; 00065 } 00066 snprintf(buf, 256, "/sys/block/%s/pid", devname); 00067 if((fd=open(buf, O_RDONLY))<0) { 00068 if(errno==ENOENT) { 00069 return 1; 00070 } else { 00071 return 2; 00072 } 00073 } 00074 len=read(fd, buf, 256); 00075 if(len >= 0) 00076 buf[len]='\0'; 00077 if(do_print) printf("%s\n", buf); 00078 return 0; 00079 } 00080 00081 int opennet(char *name, char* portstr, int sdp) { 00082 int sock; 00083 struct addrinfo hints; 00084 struct addrinfo *ai = NULL; 00085 struct addrinfo *rp = NULL; 00086 int e; 00087 00088 memset(&hints,'\0',sizeof(hints)); 00089 hints.ai_family = AF_UNSPEC; 00090 hints.ai_socktype = SOCK_STREAM; 00091 hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; 00092 hints.ai_protocol = IPPROTO_TCP; 00093 00094 e = getaddrinfo(name, portstr, &hints, &ai); 00095 00096 if(e != 0) { 00097 fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e)); 00098 freeaddrinfo(ai); 00099 return -1; 00100 } 00101 00102 if(sdp) { 00103 #ifdef WITH_SDP 00104 if (ai->ai_family == AF_INET) 00105 ai->ai_family = AF_INET_SDP; 00106 else (ai->ai_family == AF_INET6) 00107 ai->ai_family = AF_INET6_SDP; 00108 #else 00109 err("Can't do SDP: I was not compiled with SDP support!"); 00110 #endif 00111 } 00112 00113 for(rp = ai; rp != NULL; rp = rp->ai_next) { 00114 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 00115 00116 if(sock == -1) 00117 continue; /* error */ 00118 00119 if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) 00120 break; /* success */ 00121 00122 close(sock); 00123 } 00124 00125 if (rp == NULL) { 00126 err_nonfatal("Socket failed: %m"); 00127 return -1; 00128 } 00129 00130 setmysockopt(sock); 00131 00132 freeaddrinfo(ai); 00133 return sock; 00134 } 00135 00136 void ask_list(int sock) { 00137 uint32_t opt; 00138 uint32_t opt_server; 00139 uint32_t len; 00140 uint32_t reptype; 00141 uint64_t magic; 00142 const int BUF_SIZE = 1024; 00143 char buf[BUF_SIZE]; 00144 00145 magic = ntohll(opts_magic); 00146 if (write(sock, &magic, sizeof(magic)) < 0) 00147 err("Failed/2.2: %m"); 00148 00149 /* Ask for the list */ 00150 opt = htonl(NBD_OPT_LIST); 00151 if(write(sock, &opt, sizeof(opt)) < 0) { 00152 err("writing list option failed: %m"); 00153 } 00154 /* Send the length (zero) */ 00155 len = htonl(0); 00156 if(write(sock, &len, sizeof(len)) < 0) { 00157 err("writing length failed: %m"); 00158 } 00159 /* newline, move away from the "Negotiation:" line */ 00160 printf("\n"); 00161 do { 00162 memset(buf, 0, 1024); 00163 if(read(sock, &magic, sizeof(magic)) < 0) { 00164 err("Reading magic from server: %m"); 00165 } 00166 if(read(sock, &opt_server, sizeof(opt_server)) < 0) { 00167 err("Reading option: %m"); 00168 } 00169 if(read(sock, &reptype, sizeof(reptype)) <0) { 00170 err("Reading reply from server: %m"); 00171 } 00172 if(read(sock, &len, sizeof(len)) < 0) { 00173 err("Reading length from server: %m"); 00174 } 00175 magic=ntohll(magic); 00176 len=ntohl(len); 00177 reptype=ntohl(reptype); 00178 if(magic != rep_magic) { 00179 err("Not enough magic from server"); 00180 } 00181 if(reptype & NBD_REP_FLAG_ERROR) { 00182 switch(reptype) { 00183 case NBD_REP_ERR_POLICY: 00184 fprintf(stderr, "\nE: listing not allowed by server.\n"); 00185 break; 00186 default: 00187 fprintf(stderr, "\nE: unexpected error from server.\n"); 00188 break; 00189 } 00190 if(len > 0 && len < BUF_SIZE) { 00191 if(len=read(sock, buf, len) < 0) { 00192 fprintf(stderr, "\nE: could not read error message from server\n"); 00193 } 00194 buf[len] = '\0'; 00195 fprintf(stderr, "Server said: %s\n", buf); 00196 } 00197 exit(EXIT_FAILURE); 00198 } else { 00199 if(len) { 00200 if(reptype != NBD_REP_SERVER) { 00201 err("Server sent us a reply we don't understand!"); 00202 } 00203 if(read(sock, &len, sizeof(len)) < 0) { 00204 fprintf(stderr, "\nE: could not read export name length from server\n"); 00205 exit(EXIT_FAILURE); 00206 } 00207 len=ntohl(len); 00208 if (len >= BUF_SIZE) { 00209 fprintf(stderr, "\nE: export name on server too long\n"); 00210 exit(EXIT_FAILURE); 00211 } 00212 if(read(sock, buf, len) < 0) { 00213 fprintf(stderr, "\nE: could not read export name from server\n"); 00214 exit(EXIT_FAILURE); 00215 } 00216 buf[len] = 0; 00217 printf("%s\n", buf); 00218 } 00219 } 00220 } while(reptype != NBD_REP_ACK); 00221 opt=htonl(NBD_OPT_ABORT); 00222 len=htonl(0); 00223 magic=htonll(opts_magic); 00224 if (write(sock, &magic, sizeof(magic)) < 0) 00225 err("Failed/2.2: %m"); 00226 if (write(sock, &opt, sizeof(opt)) < 0) 00227 err("Failed writing abort"); 00228 if (write(sock, &len, sizeof(len)) < 0) 00229 err("Failed writing length"); 00230 } 00231 00232 void negotiate(int sock, u64 *rsize64, u32 *flags, char* name, uint32_t needed_flags, uint32_t client_flags, uint32_t do_opts) { 00233 u64 magic, size64; 00234 uint16_t tmp; 00235 char buf[256] = "\0\0\0\0\0\0\0\0\0"; 00236 00237 printf("Negotiation: "); 00238 if (read(sock, buf, 8) < 0) 00239 err("Failed/1: %m"); 00240 if (strlen(buf)==0) 00241 err("Server closed connection"); 00242 if (strcmp(buf, INIT_PASSWD)) 00243 err("INIT_PASSWD bad"); 00244 printf("."); 00245 if (read(sock, &magic, sizeof(magic)) < 0) 00246 err("Failed/2: %m"); 00247 magic = ntohll(magic); 00248 if(name) { 00249 uint32_t opt; 00250 uint32_t namesize; 00251 00252 if (magic != opts_magic) { 00253 if(magic == cliserv_magic) { 00254 err("It looks like you're trying to connect to an oldstyle server with a named export. This won't work."); 00255 } 00256 } 00257 printf("."); 00258 if(read(sock, &tmp, sizeof(uint16_t)) < 0) { 00259 err("Failed reading flags: %m"); 00260 } 00261 *flags = ((u32)ntohs(tmp)); 00262 if((needed_flags & *flags) != needed_flags) { 00263 /* There's currently really only one reason why this 00264 * check could possibly fail, but we may need to change 00265 * this error message in the future... */ 00266 fprintf(stderr, "\nE: Server does not support listing exports\n"); 00267 exit(EXIT_FAILURE); 00268 } 00269 00270 client_flags = htonl(client_flags); 00271 if (write(sock, &client_flags, sizeof(client_flags)) < 0) 00272 err("Failed/2.1: %m"); 00273 00274 if(do_opts & NBDC_DO_LIST) { 00275 ask_list(sock); 00276 exit(EXIT_SUCCESS); 00277 } 00278 00279 /* Write the export name that we're after */ 00280 magic = htonll(opts_magic); 00281 if (write(sock, &magic, sizeof(magic)) < 0) 00282 err("Failed/2.2: %m"); 00283 00284 opt = ntohl(NBD_OPT_EXPORT_NAME); 00285 if (write(sock, &opt, sizeof(opt)) < 0) 00286 err("Failed/2.3: %m"); 00287 namesize = (u32)strlen(name); 00288 namesize = ntohl(namesize); 00289 if (write(sock, &namesize, sizeof(namesize)) < 0) 00290 err("Failed/2.4: %m"); 00291 if (write(sock, name, strlen(name)) < 0) 00292 err("Failed/2.4: %m"); 00293 } else { 00294 if (magic != cliserv_magic) { 00295 if(magic != opts_magic) 00296 err("Not enough cliserv_magic"); 00297 else 00298 err("It looks like you're trying to connect to a newstyle server with the oldstyle protocol. Try the -N option."); 00299 } 00300 printf("."); 00301 } 00302 00303 if (read(sock, &size64, sizeof(size64)) <= 0) { 00304 if (!errno) 00305 err("Server closed connection"); 00306 err("Failed/3: %m\n"); 00307 } 00308 size64 = ntohll(size64); 00309 00310 if ((size64>>12) > (uint64_t)~0UL) { 00311 printf("size = %luMB", (unsigned long)(size64>>20)); 00312 err("Exported device is too big for me. Get 64-bit machine :-(\n"); 00313 } else 00314 printf("size = %luMB", (unsigned long)(size64>>20)); 00315 00316 if(!name) { 00317 if (read(sock, flags, sizeof(*flags)) < 0) 00318 err("Failed/4: %m\n"); 00319 *flags = ntohl(*flags); 00320 } else { 00321 if(read(sock, &tmp, sizeof(tmp)) < 0) 00322 err("Failed/4: %m\n"); 00323 *flags |= (uint32_t)ntohs(tmp); 00324 } 00325 00326 if (read(sock, &buf, 124) < 0) 00327 err("Failed/5: %m\n"); 00328 printf("\n"); 00329 00330 *rsize64 = size64; 00331 } 00332 00333 void setsizes(int nbd, u64 size64, int blocksize, u32 flags) { 00334 unsigned long size; 00335 int read_only = (flags & NBD_FLAG_READ_ONLY) ? 1 : 0; 00336 00337 if (size64>>12 > (uint64_t)~0UL) 00338 err("Device too large.\n"); 00339 else { 00340 if (ioctl(nbd, NBD_SET_BLKSIZE, 4096UL) < 0) 00341 err("Ioctl/1.1a failed: %m\n"); 00342 size = (unsigned long)(size64>>12); 00343 if (ioctl(nbd, NBD_SET_SIZE_BLOCKS, size) < 0) 00344 err("Ioctl/1.1b failed: %m\n"); 00345 if (ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long)blocksize) < 0) 00346 err("Ioctl/1.1c failed: %m\n"); 00347 fprintf(stderr, "bs=%d, sz=%llu bytes\n", blocksize, 4096ULL*size); 00348 } 00349 00350 ioctl(nbd, NBD_CLEAR_SOCK); 00351 00352 /* ignore error as kernel may not support */ 00353 ioctl(nbd, NBD_SET_FLAGS, (unsigned long) flags); 00354 00355 if (ioctl(nbd, BLKROSET, (unsigned long) &read_only) < 0) 00356 err("Unable to set read-only attribute for device"); 00357 } 00358 00359 void set_timeout(int nbd, int timeout) { 00360 if (timeout) { 00361 if (ioctl(nbd, NBD_SET_TIMEOUT, (unsigned long)timeout) < 0) 00362 err("Ioctl NBD_SET_TIMEOUT failed: %m\n"); 00363 fprintf(stderr, "timeout=%d\n", timeout); 00364 } 00365 } 00366 00367 void finish_sock(int sock, int nbd, int swap) { 00368 if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) 00369 err("Ioctl NBD_SET_SOCK failed: %m\n"); 00370 00371 if (swap) 00372 mlockall(MCL_CURRENT | MCL_FUTURE); 00373 } 00374 00375 static int 00376 oom_adjust(const char *file, const char *value) 00377 { 00378 int fd, rc; 00379 size_t len; 00380 00381 fd = open(file, O_WRONLY); 00382 if (fd < 0) 00383 return -1; 00384 len = strlen(value); 00385 rc = write(fd, value, len) != (ssize_t) len; 00386 close(fd); 00387 return rc ? -1 : 0; 00388 } 00389 00390 void usage(char* errmsg, ...) { 00391 if(errmsg) { 00392 char tmp[256]; 00393 va_list ap; 00394 va_start(ap, errmsg); 00395 snprintf(tmp, 256, "ERROR: %s\n\n", errmsg); 00396 vfprintf(stderr, tmp, ap); 00397 va_end(ap); 00398 } else { 00399 fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION); 00400 } 00401 fprintf(stderr, "Usage: nbd-client host port nbd_device [-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S] [-persist|-p] [-nofork|-n] [-systemd-mark|-m]\n"); 00402 fprintf(stderr, "Or : nbd-client -name|-N name host [port] nbd_device [-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S] [-persist|-p] [-nofork|-n]\n"); 00403 fprintf(stderr, "Or : nbd-client -d nbd_device\n"); 00404 fprintf(stderr, "Or : nbd-client -c nbd_device\n"); 00405 fprintf(stderr, "Or : nbd-client -h|--help\n"); 00406 fprintf(stderr, "Or : nbd-client -l|--list host\n"); 00407 fprintf(stderr, "Default value for blocksize is 1024 (recommended for ethernet)\n"); 00408 fprintf(stderr, "Allowed values for blocksize are 512,1024,2048,4096\n"); /* will be checked in kernel :) */ 00409 fprintf(stderr, "Note, that kernel 2.4.2 and older ones do not work correctly with\n"); 00410 fprintf(stderr, "blocksizes other than 1024 without patches\n"); 00411 fprintf(stderr, "Default value for port with -N is 10809. Note that port must always be numeric\n"); 00412 } 00413 00414 void disconnect(char* device) { 00415 int nbd = open(device, O_RDWR); 00416 00417 if (nbd < 0) 00418 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded."); 00419 printf("disconnect, "); 00420 if (ioctl(nbd, NBD_DISCONNECT)<0) 00421 err("Ioctl failed: %m\n"); 00422 printf("sock, "); 00423 if (ioctl(nbd, NBD_CLEAR_SOCK)<0) 00424 err("Ioctl failed: %m\n"); 00425 printf("done\n"); 00426 } 00427 00428 int main(int argc, char *argv[]) { 00429 char* port=NULL; 00430 int sock, nbd; 00431 int blocksize=1024; 00432 char *hostname=NULL; 00433 char *nbddev=NULL; 00434 int swap=0; 00435 int cont=0; 00436 int timeout=0; 00437 int sdp=0; 00438 int G_GNUC_UNUSED nofork=0; // if -dNOFORK 00439 u64 size64; 00440 u32 flags; 00441 int c; 00442 int nonspecial=0; 00443 char* name=NULL; 00444 uint32_t needed_flags=0; 00445 uint32_t cflags=0; 00446 uint32_t opts=0; 00447 sigset_t block, old; 00448 struct sigaction sa; 00449 struct option long_options[] = { 00450 { "block-size", required_argument, NULL, 'b' }, 00451 { "check", required_argument, NULL, 'c' }, 00452 { "disconnect", required_argument, NULL, 'd' }, 00453 { "help", no_argument, NULL, 'h' }, 00454 { "list", no_argument, NULL, 'l' }, 00455 { "name", required_argument, NULL, 'N' }, 00456 { "nofork", no_argument, NULL, 'n' }, 00457 { "persist", no_argument, NULL, 'p' }, 00458 { "sdp", no_argument, NULL, 'S' }, 00459 { "swap", no_argument, NULL, 's' }, 00460 { "systemd-mark", no_argument, NULL, 'm' }, 00461 { "timeout", required_argument, NULL, 't' }, 00462 { 0, 0, 0, 0 }, 00463 }; 00464 00465 logging(); 00466 00467 while((c=getopt_long_only(argc, argv, "-b:c:d:hlnN:pSst:", long_options, NULL))>=0) { 00468 switch(c) { 00469 case 1: 00470 // non-option argument 00471 if(strchr(optarg, '=')) { 00472 // old-style 'bs=' or 'timeout=' 00473 // argument 00474 fprintf(stderr, "WARNING: old-style command-line argument encountered. This is deprecated.\n"); 00475 if(!strncmp(optarg, "bs=", 3)) { 00476 optarg+=3; 00477 goto blocksize; 00478 } 00479 if(!strncmp(optarg, "timeout=", 8)) { 00480 optarg+=8; 00481 goto timeout; 00482 } 00483 usage("unknown option %s encountered", optarg); 00484 exit(EXIT_FAILURE); 00485 } 00486 switch(nonspecial++) { 00487 case 0: 00488 // host 00489 hostname=optarg; 00490 break; 00491 case 1: 00492 // port 00493 if(!strtol(optarg, NULL, 0)) { 00494 // not parseable as a number, assume it's the device and we have a name 00495 nbddev = optarg; 00496 nonspecial++; 00497 } else { 00498 port = optarg; 00499 } 00500 break; 00501 case 2: 00502 // device 00503 nbddev = optarg; 00504 break; 00505 default: 00506 usage("too many non-option arguments specified"); 00507 exit(EXIT_FAILURE); 00508 } 00509 break; 00510 case 'b': 00511 blocksize: 00512 blocksize=(int)strtol(optarg, NULL, 0); 00513 break; 00514 case 'c': 00515 return check_conn(optarg, 1); 00516 case 'd': 00517 disconnect(optarg); 00518 exit(EXIT_SUCCESS); 00519 case 'h': 00520 usage(NULL); 00521 exit(EXIT_SUCCESS); 00522 case 'l': 00523 needed_flags |= NBD_FLAG_FIXED_NEWSTYLE; 00524 cflags |= NBD_FLAG_C_FIXED_NEWSTYLE; 00525 opts |= NBDC_DO_LIST; 00526 name=""; 00527 nbddev=""; 00528 port = NBD_DEFAULT_PORT; 00529 break; 00530 case 'm': 00531 argv[0][0] = '@'; 00532 break; 00533 case 'n': 00534 nofork=1; 00535 break; 00536 case 'N': 00537 name=optarg; 00538 if(!port) { 00539 port = NBD_DEFAULT_PORT; 00540 } 00541 break; 00542 case 'p': 00543 cont=1; 00544 break; 00545 case 's': 00546 swap=1; 00547 break; 00548 case 'S': 00549 sdp=1; 00550 break; 00551 case 't': 00552 timeout: 00553 timeout=strtol(optarg, NULL, 0); 00554 break; 00555 default: 00556 fprintf(stderr, "E: option eaten by 42 mice\n"); 00557 exit(EXIT_FAILURE); 00558 } 00559 } 00560 00561 if((!port && !name) || !hostname || !nbddev) { 00562 usage("not enough information specified"); 00563 exit(EXIT_FAILURE); 00564 } 00565 00566 sock = opennet(hostname, port, sdp); 00567 if (sock < 0) 00568 exit(EXIT_FAILURE); 00569 00570 negotiate(sock, &size64, &flags, name, needed_flags, cflags, opts); 00571 00572 nbd = open(nbddev, O_RDWR); 00573 if (nbd < 0) 00574 err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded."); 00575 00576 setsizes(nbd, size64, blocksize, flags); 00577 set_timeout(nbd, timeout); 00578 finish_sock(sock, nbd, swap); 00579 if (swap) { 00580 /* try linux >= 2.6.36 interface first */ 00581 if (oom_adjust("/proc/self/oom_score_adj", "-1000")) { 00582 /* fall back to linux <= 2.6.35 interface */ 00583 oom_adjust("/proc/self/oom_adj", "-17"); 00584 } 00585 } 00586 00587 /* Go daemon */ 00588 00589 #ifndef NOFORK 00590 if(!nofork) { 00591 if (daemon(0,0) < 0) 00592 err("Cannot detach from terminal"); 00593 } 00594 00595 memset(&sa, 0, sizeof(sa)); 00596 sa.sa_handler = SIG_IGN; 00597 sigaction(SIGCHLD, &sa, NULL); 00598 #endif 00599 do { 00600 #ifndef NOFORK 00601 00602 sigfillset(&block); 00603 sigdelset(&block, SIGKILL); 00604 sigdelset(&block, SIGTERM); 00605 sigdelset(&block, SIGPIPE); 00606 sigprocmask(SIG_SETMASK, &block, &old); 00607 00608 if (!fork()) { 00609 /* Due to a race, the kernel NBD driver cannot 00610 * call for a reread of the partition table 00611 * in the handling of the NBD_DO_IT ioctl(). 00612 * Therefore, this is done in the first open() 00613 * of the device. We therefore make sure that 00614 * the device is opened at least once after the 00615 * connection was made. This has to be done in a 00616 * separate process, since the NBD_DO_IT ioctl() 00617 * does not return until the NBD device has 00618 * disconnected. 00619 */ 00620 while(check_conn(nbddev, 0)) { 00621 sleep(1); 00622 } 00623 open(nbddev, O_RDONLY); 00624 exit(0); 00625 } 00626 #endif 00627 00628 if (ioctl(nbd, NBD_DO_IT) < 0) { 00629 int error = errno; 00630 fprintf(stderr, "nbd,%d: Kernel call returned: %d", getpid(), error); 00631 if(error==EBADR) { 00632 /* The user probably did 'nbd-client -d' on us. 00633 * quit */ 00634 cont=0; 00635 } else { 00636 if(cont) { 00637 u64 new_size; 00638 u32 new_flags; 00639 00640 close(sock); close(nbd); 00641 for (;;) { 00642 fprintf(stderr, " Reconnecting\n"); 00643 sock = opennet(hostname, port, sdp); 00644 if (sock >= 0) 00645 break; 00646 sleep (1); 00647 } 00648 nbd = open(nbddev, O_RDWR); 00649 if (nbd < 0) 00650 err("Cannot open NBD: %m"); 00651 negotiate(sock, &new_size, &new_flags, name, needed_flags, cflags, opts); 00652 if (size64 != new_size) { 00653 err("Size of the device changed. Bye"); 00654 } 00655 setsizes(nbd, size64, blocksize, 00656 new_flags); 00657 00658 set_timeout(nbd, timeout); 00659 finish_sock(sock,nbd,swap); 00660 } 00661 } 00662 } else { 00663 /* We're on 2.4. It's not clearly defined what exactly 00664 * happened at this point. Probably best to quit, now 00665 */ 00666 fprintf(stderr, "Kernel call returned."); 00667 cont=0; 00668 } 00669 } while(cont); 00670 printf("sock, "); 00671 ioctl(nbd, NBD_CLEAR_SOCK); 00672 printf("done\n"); 00673 return 0; 00674 }
1.7.3