Revision 3b05a8e9 qemu-nbd.c

b/qemu-nbd.c
55 55
"  -n, --nocache        disable host cache\n"
56 56
"  -c, --connect=DEV    connect FILE to the local NBD device DEV\n"
57 57
"  -d, --disconnect     disconnect the specified device\n"
58
"  -e, --shared=NUM     device can be shared by NUM clients (default '1')\n"
58 59
"  -v, --verbose        display extra debugging information\n"
59 60
"  -h, --help           display this help and exit\n"
60 61
"  -V, --version        output version information and exit\n"
......
182 183
    bool disconnect = false;
183 184
    const char *bindto = "0.0.0.0";
184 185
    int port = 1024;
185
    int sock, csock;
186 186
    struct sockaddr_in addr;
187 187
    socklen_t addr_len = sizeof(addr);
188 188
    off_t fd_size;
189 189
    char *device = NULL;
190 190
    char *socket = NULL;
191 191
    char sockpath[128];
192
    const char *sopt = "hVbo:p:rsnP:c:dvk:";
192
    const char *sopt = "hVbo:p:rsnP:c:dvk:e:";
193 193
    struct option lopt[] = {
194 194
        { "help", 0, 0, 'h' },
195 195
        { "version", 0, 0, 'V' },
......
203 203
        { "disconnect", 0, 0, 'd' },
204 204
        { "snapshot", 0, 0, 's' },
205 205
        { "nocache", 0, 0, 'n' },
206
        { "shared", 1, 0, 'e' },
206 207
        { "verbose", 0, 0, 'v' },
207 208
        { NULL, 0, 0, 0 }
208 209
    };
......
212 213
    char *end;
213 214
    int flags = 0;
214 215
    int partition = -1;
215
    int fd;
216 216
    int ret;
217
    int shared = 1;
217 218
    uint8_t *data;
219
    fd_set fds;
220
    int *sharing_fds;
221
    int fd;
222
    int i;
223
    int nb_fds = 0;
224
    int max_fd;
218 225

  
219 226
    while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
220 227
        switch (ch) {
......
267 274
        case 'c':
268 275
            device = optarg;
269 276
            break;
277
        case 'e':
278
            shared = strtol(optarg, &end, 0);
279
            if (*end) {
280
                errx(EINVAL, "Invalid shared device number '%s'", optarg);
281
            }
282
            if (shared < 1) {
283
                errx(EINVAL, "Shared device number must be greater than 0\n");
284
            }
285
            break;
270 286
        case 'v':
271 287
            verbose = 1;
272 288
            break;
......
320 336
        errx(errno, "Could not find partition %d", partition);
321 337

  
322 338
    if (device) {
323
	pid_t pid;
324
	if (!verbose)
339
        pid_t pid;
340
        int sock;
341

  
342
        if (!verbose)
325 343
            daemon(0, 0);	/* detach client and server */
326 344

  
327 345
        if (socket == NULL) {
......
384 402
        /* children */
385 403
    }
386 404

  
405
    sharing_fds = qemu_malloc((shared + 1) * sizeof(int));
406
    if (sharing_fds == NULL)
407
        errx(ENOMEM, "Cannot allocate sharing fds");
408

  
387 409
    if (socket) {
388
        sock = unix_socket_incoming(socket);
410
        sharing_fds[0] = unix_socket_incoming(socket);
389 411
    } else {
390
        sock = tcp_socket_incoming(bindto, port);
412
        sharing_fds[0] = tcp_socket_incoming(bindto, port);
391 413
    }
392 414

  
393
    if (sock == -1)
415
    if (sharing_fds[0] == -1)
394 416
        return 1;
417
    max_fd = sharing_fds[0];
418
    nb_fds++;
395 419

  
396
    csock = accept(sock,
397
               (struct sockaddr *)&addr,
398
               &addr_len);
399
    if (csock == -1)
400
        return 1;
420
    data = qemu_memalign(512, NBD_BUFFER_SIZE);
421
    if (data == NULL)
422
        errx(ENOMEM, "Cannot allocate data buffer");
401 423

  
402
    /* new fd_size is calculated by find_partition */
403
    if (nbd_negotiate(bs, csock, fd_size) == -1)
404
        return 1;
424
    do {
405 425

  
406
    data = qemu_memalign(512, NBD_BUFFER_SIZE);
407
    while (nbd_trip(bs, csock, fd_size, dev_offset, &offset, readonly,
408
                    data, NBD_BUFFER_SIZE) == 0);
426
        FD_ZERO(&fds);
427
        for (i = 0; i < nb_fds; i++)
428
            FD_SET(sharing_fds[i], &fds);
429

  
430
        ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
431
        if (ret == -1)
432
            break;
433

  
434
        if (FD_ISSET(sharing_fds[0], &fds))
435
            ret--;
436
        for (i = 1; i < nb_fds && ret; i++) {
437
            if (FD_ISSET(sharing_fds[i], &fds)) {
438
                if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
439
                    &offset, readonly, data, NBD_BUFFER_SIZE) != 0) {
440
                    close(sharing_fds[i]);
441
                    nb_fds--;
442
                    sharing_fds[i] = sharing_fds[nb_fds];
443
                    i--;
444
                }
445
                ret--;
446
            }
447
        }
448
        /* new connection ? */
449
        if (FD_ISSET(sharing_fds[0], &fds)) {
450
            if (nb_fds < shared + 1) {
451
                sharing_fds[nb_fds] = accept(sharing_fds[0],
452
                                             (struct sockaddr *)&addr,
453
                                             &addr_len);
454
                if (sharing_fds[nb_fds] != -1 &&
455
                    nbd_negotiate(bs, sharing_fds[nb_fds], fd_size) != -1) {
456
                        if (sharing_fds[nb_fds] > max_fd)
457
                            max_fd = sharing_fds[nb_fds];
458
                        nb_fds++;
459
                }
460
            }
461
        }
462
    } while (nb_fds > 1);
409 463
    qemu_free(data);
410 464

  
411
    close(csock);
412
    close(sock);
465
    close(sharing_fds[0]);
413 466
    bdrv_close(bs);
467
    qemu_free(sharing_fds);
414 468
    if (socket)
415 469
        unlink(socket);
416 470

  

Also available in: Unified diff