qemu-nbd: rewrite termination conditions to use a state machine
Use a simple state machine with the following states: - RUNNING => accepting connections - TERMINATE => main loop must call nbd_export_close/put, and not accept connections anymore - TERMINATING => waiting for pending requests to finish - TERMINATED => the NBDExport has been closed Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
0ddf08db22
commit
7860a380ac
37
qemu-nbd.c
37
qemu-nbd.c
@ -41,8 +41,8 @@ static NBDExport *exp;
|
||||
static int verbose;
|
||||
static char *srcpath;
|
||||
static char *sockpath;
|
||||
static bool sigterm_reported;
|
||||
static bool nbd_started;
|
||||
static int persistent = 0;
|
||||
static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state;
|
||||
static int shared = 1;
|
||||
static int nb_fds;
|
||||
|
||||
@ -186,7 +186,7 @@ static int find_partition(BlockDriverState *bs, int partition,
|
||||
|
||||
static void termsig_handler(int signum)
|
||||
{
|
||||
sigterm_reported = true;
|
||||
state = TERMINATE;
|
||||
qemu_notify_event();
|
||||
}
|
||||
|
||||
@ -269,10 +269,20 @@ static int nbd_can_accept(void *opaque)
|
||||
return nb_fds < shared;
|
||||
}
|
||||
|
||||
static void nbd_export_closed(NBDExport *exp)
|
||||
{
|
||||
assert(state == TERMINATING);
|
||||
state = TERMINATED;
|
||||
}
|
||||
|
||||
static void nbd_client_closed(NBDClient *client)
|
||||
{
|
||||
nb_fds--;
|
||||
if (nb_fds == 0 && !persistent && state == RUNNING) {
|
||||
state = TERMINATE;
|
||||
}
|
||||
qemu_notify_event();
|
||||
nbd_client_put(client);
|
||||
}
|
||||
|
||||
static void nbd_accept(void *opaque)
|
||||
@ -282,7 +292,11 @@ static void nbd_accept(void *opaque)
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
||||
nbd_started = true;
|
||||
if (state >= TERMINATE) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) {
|
||||
nb_fds++;
|
||||
}
|
||||
@ -329,7 +343,6 @@ int main(int argc, char **argv)
|
||||
int partition = -1;
|
||||
int ret;
|
||||
int fd;
|
||||
int persistent = 0;
|
||||
bool seen_cache = false;
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
bool seen_aio = false;
|
||||
@ -546,7 +559,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, NULL);
|
||||
exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed);
|
||||
|
||||
if (sockpath) {
|
||||
fd = unix_socket_incoming(sockpath);
|
||||
@ -581,14 +594,18 @@ int main(int argc, char **argv)
|
||||
err(EXIT_FAILURE, "Could not chdir to root directory");
|
||||
}
|
||||
|
||||
state = RUNNING;
|
||||
do {
|
||||
main_loop_wait(false);
|
||||
} while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0));
|
||||
if (state == TERMINATE) {
|
||||
state = TERMINATING;
|
||||
nbd_export_close(exp);
|
||||
nbd_export_put(exp);
|
||||
exp = NULL;
|
||||
}
|
||||
} while (state != TERMINATED);
|
||||
|
||||
nbd_export_close(exp);
|
||||
nbd_export_put(exp);
|
||||
bdrv_close(bs);
|
||||
|
||||
if (sockpath) {
|
||||
unlink(sockpath);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user