Back to index

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