Revision 7860a380

b/qemu-nbd.c
41 41
static int verbose;
42 42
static char *srcpath;
43 43
static char *sockpath;
44
static bool sigterm_reported;
45
static bool nbd_started;
44
static int persistent = 0;
45
static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state;
46 46
static int shared = 1;
47 47
static int nb_fds;
48 48

  
......
186 186

  
187 187
static void termsig_handler(int signum)
188 188
{
189
    sigterm_reported = true;
189
    state = TERMINATE;
190 190
    qemu_notify_event();
191 191
}
192 192

  
......
269 269
    return nb_fds < shared;
270 270
}
271 271

  
272
static void nbd_export_closed(NBDExport *exp)
273
{
274
    assert(state == TERMINATING);
275
    state = TERMINATED;
276
}
277

  
272 278
static void nbd_client_closed(NBDClient *client)
273 279
{
274 280
    nb_fds--;
281
    if (nb_fds == 0 && !persistent && state == RUNNING) {
282
        state = TERMINATE;
283
    }
275 284
    qemu_notify_event();
285
    nbd_client_put(client);
276 286
}
277 287

  
278 288
static void nbd_accept(void *opaque)
......
282 292
    socklen_t addr_len = sizeof(addr);
283 293

  
284 294
    int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
285
    nbd_started = true;
295
    if (state >= TERMINATE) {
296
        close(fd);
297
        return;
298
    }
299

  
286 300
    if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) {
287 301
        nb_fds++;
288 302
    }
......
329 343
    int partition = -1;
330 344
    int ret;
331 345
    int fd;
332
    int persistent = 0;
333 346
    bool seen_cache = false;
334 347
#ifdef CONFIG_LINUX_AIO
335 348
    bool seen_aio = false;
......
546 559
        }
547 560
    }
548 561

  
549
    exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, NULL);
562
    exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed);
550 563

  
551 564
    if (sockpath) {
552 565
        fd = unix_socket_incoming(sockpath);
......
581 594
        err(EXIT_FAILURE, "Could not chdir to root directory");
582 595
    }
583 596

  
597
    state = RUNNING;
584 598
    do {
585 599
        main_loop_wait(false);
586
    } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0));
600
        if (state == TERMINATE) {
601
            state = TERMINATING;
602
            nbd_export_close(exp);
603
            nbd_export_put(exp);
604
            exp = NULL;
605
        }
606
    } while (state != TERMINATED);
587 607

  
588
    nbd_export_close(exp);
589
    nbd_export_put(exp);
590 608
    bdrv_close(bs);
591

  
592 609
    if (sockpath) {
593 610
        unlink(sockpath);
594 611
    }

Also available in: Unified diff