mirror of https://github.com/xqemu/xqemu.git
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 int verbose;
|
||||||
static char *srcpath;
|
static char *srcpath;
|
||||||
static char *sockpath;
|
static char *sockpath;
|
||||||
static bool sigterm_reported;
|
static int persistent = 0;
|
||||||
static bool nbd_started;
|
static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state;
|
||||||
static int shared = 1;
|
static int shared = 1;
|
||||||
static int nb_fds;
|
static int nb_fds;
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ static int find_partition(BlockDriverState *bs, int partition,
|
||||||
|
|
||||||
static void termsig_handler(int signum)
|
static void termsig_handler(int signum)
|
||||||
{
|
{
|
||||||
sigterm_reported = true;
|
state = TERMINATE;
|
||||||
qemu_notify_event();
|
qemu_notify_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,10 +269,20 @@ static int nbd_can_accept(void *opaque)
|
||||||
return nb_fds < shared;
|
return nb_fds < shared;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nbd_export_closed(NBDExport *exp)
|
||||||
|
{
|
||||||
|
assert(state == TERMINATING);
|
||||||
|
state = TERMINATED;
|
||||||
|
}
|
||||||
|
|
||||||
static void nbd_client_closed(NBDClient *client)
|
static void nbd_client_closed(NBDClient *client)
|
||||||
{
|
{
|
||||||
nb_fds--;
|
nb_fds--;
|
||||||
|
if (nb_fds == 0 && !persistent && state == RUNNING) {
|
||||||
|
state = TERMINATE;
|
||||||
|
}
|
||||||
qemu_notify_event();
|
qemu_notify_event();
|
||||||
|
nbd_client_put(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nbd_accept(void *opaque)
|
static void nbd_accept(void *opaque)
|
||||||
|
@ -282,7 +292,11 @@ static void nbd_accept(void *opaque)
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
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)) {
|
if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) {
|
||||||
nb_fds++;
|
nb_fds++;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +343,6 @@ int main(int argc, char **argv)
|
||||||
int partition = -1;
|
int partition = -1;
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
int persistent = 0;
|
|
||||||
bool seen_cache = false;
|
bool seen_cache = false;
|
||||||
#ifdef CONFIG_LINUX_AIO
|
#ifdef CONFIG_LINUX_AIO
|
||||||
bool seen_aio = false;
|
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) {
|
if (sockpath) {
|
||||||
fd = unix_socket_incoming(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");
|
err(EXIT_FAILURE, "Could not chdir to root directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = RUNNING;
|
||||||
do {
|
do {
|
||||||
main_loop_wait(false);
|
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);
|
bdrv_close(bs);
|
||||||
|
|
||||||
if (sockpath) {
|
if (sockpath) {
|
||||||
unlink(sockpath);
|
unlink(sockpath);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue