Revision a61c6782 qemu-nbd.c

b/qemu-nbd.c
35 35

  
36 36
#define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
37 37

  
38
static int sigterm_wfd;
39 38
static NBDExport *exp;
40 39
static int verbose;
41 40
static char *device;
42 41
static char *srcpath;
43 42
static char *sockpath;
43
static bool sigterm_reported;
44
static bool nbd_started;
45
static int shared = 1;
46
static int nb_fds;
44 47

  
45 48
static void usage(const char *name)
46 49
{
......
169 172

  
170 173
static void termsig_handler(int signum)
171 174
{
172
    static int sigterm_reported;
173
    if (!sigterm_reported) {
174
        sigterm_reported = (write(sigterm_wfd, "", 1) == 1);
175
    }
175
    sigterm_reported = true;
176
    qemu_notify_event();
176 177
}
177 178

  
178 179
static void *show_parts(void *arg)
......
243 244
    return (void *) EXIT_FAILURE;
244 245
}
245 246

  
247
static int nbd_can_accept(void *opaque)
248
{
249
    return nb_fds < shared;
250
}
251

  
252
static void nbd_read(void *opaque)
253
{
254
    int fd = (uintptr_t) opaque;
255

  
256
    if (nbd_trip(exp, fd) != 0) {
257
        qemu_set_fd_handler2(fd, NULL, NULL, NULL, NULL);
258
        close(fd);
259
        nb_fds--;
260
    }
261
}
262

  
263
static void nbd_accept(void *opaque)
264
{
265
    int server_fd = (uintptr_t) opaque;
266
    struct sockaddr_in addr;
267
    socklen_t addr_len = sizeof(addr);
268

  
269
    int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
270
    nbd_started = true;
271
    if (fd != -1 && nbd_negotiate(exp, fd) != -1) {
272
        qemu_set_fd_handler2(fd, NULL, nbd_read, NULL, (void *) (intptr_t) fd);
273
        nb_fds++;
274
    }
275
}
276

  
246 277
int main(int argc, char **argv)
247 278
{
248 279
    BlockDriverState *bs;
......
251 282
    bool disconnect = false;
252 283
    const char *bindto = "0.0.0.0";
253 284
    int port = NBD_DEFAULT_PORT;
254
    struct sockaddr_in addr;
255
    socklen_t addr_len = sizeof(addr);
256 285
    off_t fd_size;
257 286
    const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
258 287
    struct option lopt[] = {
......
280 309
    int flags = BDRV_O_RDWR;
281 310
    int partition = -1;
282 311
    int ret;
283
    int shared = 1;
284
    fd_set fds;
285
    int *sharing_fds;
286 312
    int fd;
287
    int i;
288
    int nb_fds = 0;
289
    int max_fd;
290 313
    int persistent = 0;
291 314
    pthread_t client_thread;
292 315

  
......
294 317
     * handler ensures that "qemu-nbd -v -c" exits with a nice status code.
295 318
     */
296 319
    struct sigaction sa_sigterm;
297
    int sigterm_fd[2];
298
    if (qemu_pipe(sigterm_fd) == -1) {
299
        err(EXIT_FAILURE, "Error setting up communication pipe");
300
    }
301

  
302
    sigterm_wfd = sigterm_fd[1];
303 320
    memset(&sa_sigterm, 0, sizeof(sa_sigterm));
304 321
    sa_sigterm.sa_handler = termsig_handler;
305 322
    sigaction(SIGTERM, &sa_sigterm, NULL);
......
490 507
    }
491 508

  
492 509
    exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags);
493
    sharing_fds = g_malloc((shared + 1) * sizeof(int));
494 510

  
495 511
    if (sockpath) {
496
        sharing_fds[0] = unix_socket_incoming(sockpath);
512
        fd = unix_socket_incoming(sockpath);
497 513
    } else {
498
        sharing_fds[0] = tcp_socket_incoming(bindto, port);
514
        fd = tcp_socket_incoming(bindto, port);
499 515
    }
500 516

  
501
    if (sharing_fds[0] == -1)
517
    if (fd == -1) {
502 518
        return 1;
519
    }
503 520

  
504 521
    if (device) {
505 522
        int ret;
......
514 531
        memset(&client_thread, 0, sizeof(client_thread));
515 532
    }
516 533

  
517
    max_fd = sharing_fds[0];
518
    nb_fds++;
534
    qemu_init_main_loop();
535
    qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL,
536
                         (void *)(uintptr_t)fd);
519 537

  
520 538
    do {
521
        FD_ZERO(&fds);
522
        FD_SET(sigterm_fd[0], &fds);
523
        for (i = 0; i < nb_fds; i++)
524
            FD_SET(sharing_fds[i], &fds);
525

  
526
        do {
527
            ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
528
        } while (ret == -1 && errno == EINTR);
529
        if (ret == -1 || FD_ISSET(sigterm_fd[0], &fds)) {
530
            break;
531
        }
532

  
533
        if (FD_ISSET(sharing_fds[0], &fds))
534
            ret--;
535
        for (i = 1; i < nb_fds && ret; i++) {
536
            if (FD_ISSET(sharing_fds[i], &fds)) {
537
                if (nbd_trip(exp, sharing_fds[i]) != 0) {
538
                    close(sharing_fds[i]);
539
                    nb_fds--;
540
                    sharing_fds[i] = sharing_fds[nb_fds];
541
                    i--;
542
                }
543
                ret--;
544
            }
545
        }
546
        /* new connection ? */
547
        if (FD_ISSET(sharing_fds[0], &fds)) {
548
            if (nb_fds < shared + 1) {
549
                sharing_fds[nb_fds] = accept(sharing_fds[0],
550
                                             (struct sockaddr *)&addr,
551
                                             &addr_len);
552
                if (sharing_fds[nb_fds] != -1 &&
553
                    nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) {
554
                        if (sharing_fds[nb_fds] > max_fd)
555
                            max_fd = sharing_fds[nb_fds];
556
                        nb_fds++;
557
                }
558
            }
559
        }
560
    } while (persistent || nb_fds > 1);
539
        main_loop_wait(false);
540
    } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0));
561 541

  
562
    close(sharing_fds[0]);
563 542
    nbd_export_close(exp);
564
    g_free(sharing_fds);
565 543
    if (sockpath) {
566 544
        unlink(sockpath);
567 545
    }

Also available in: Unified diff