aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2011-09-12 17:28:11 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2011-12-22 11:53:59 +0100
commita61c67828dea7c64edaf226cadb45b4ffcc1d411 (patch)
treec79d57d2d80d7617b12ed015ef7c100de964b854
parentcbcfa0418f0c196afa765f5c9837b9344d1adcf3 (diff)
qemu-nbd: use common main loop
Using a single main loop for sockets will help yielding from the socket coroutine back to the main loop, and later reentering it. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--qemu-nbd.c112
1 files changed, 45 insertions, 67 deletions
diff --git a/qemu-nbd.c b/qemu-nbd.c
index d5ac75ed5c..347c776ab9 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -35,12 +35,15 @@
#define SOCKET_PATH "/var/lock/qemu-nbd-%s"
-static int sigterm_wfd;
static NBDExport *exp;
static int verbose;
static char *device;
static char *srcpath;
static char *sockpath;
+static bool sigterm_reported;
+static bool nbd_started;
+static int shared = 1;
+static int nb_fds;
static void usage(const char *name)
{
@@ -169,10 +172,8 @@ static int find_partition(BlockDriverState *bs, int partition,
static void termsig_handler(int signum)
{
- static int sigterm_reported;
- if (!sigterm_reported) {
- sigterm_reported = (write(sigterm_wfd, "", 1) == 1);
- }
+ sigterm_reported = true;
+ qemu_notify_event();
}
static void *show_parts(void *arg)
@@ -243,6 +244,36 @@ out:
return (void *) EXIT_FAILURE;
}
+static int nbd_can_accept(void *opaque)
+{
+ return nb_fds < shared;
+}
+
+static void nbd_read(void *opaque)
+{
+ int fd = (uintptr_t) opaque;
+
+ if (nbd_trip(exp, fd) != 0) {
+ qemu_set_fd_handler2(fd, NULL, NULL, NULL, NULL);
+ close(fd);
+ nb_fds--;
+ }
+}
+
+static void nbd_accept(void *opaque)
+{
+ int server_fd = (uintptr_t) opaque;
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+
+ int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
+ nbd_started = true;
+ if (fd != -1 && nbd_negotiate(exp, fd) != -1) {
+ qemu_set_fd_handler2(fd, NULL, nbd_read, NULL, (void *) (intptr_t) fd);
+ nb_fds++;
+ }
+}
+
int main(int argc, char **argv)
{
BlockDriverState *bs;
@@ -251,8 +282,6 @@ int main(int argc, char **argv)
bool disconnect = false;
const char *bindto = "0.0.0.0";
int port = NBD_DEFAULT_PORT;
- struct sockaddr_in addr;
- socklen_t addr_len = sizeof(addr);
off_t fd_size;
const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
struct option lopt[] = {
@@ -280,13 +309,7 @@ int main(int argc, char **argv)
int flags = BDRV_O_RDWR;
int partition = -1;
int ret;
- int shared = 1;
- fd_set fds;
- int *sharing_fds;
int fd;
- int i;
- int nb_fds = 0;
- int max_fd;
int persistent = 0;
pthread_t client_thread;
@@ -294,12 +317,6 @@ int main(int argc, char **argv)
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
*/
struct sigaction sa_sigterm;
- int sigterm_fd[2];
- if (qemu_pipe(sigterm_fd) == -1) {
- err(EXIT_FAILURE, "Error setting up communication pipe");
- }
-
- sigterm_wfd = sigterm_fd[1];
memset(&sa_sigterm, 0, sizeof(sa_sigterm));
sa_sigterm.sa_handler = termsig_handler;
sigaction(SIGTERM, &sa_sigterm, NULL);
@@ -490,16 +507,16 @@ int main(int argc, char **argv)
}
exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags);
- sharing_fds = g_malloc((shared + 1) * sizeof(int));
if (sockpath) {
- sharing_fds[0] = unix_socket_incoming(sockpath);
+ fd = unix_socket_incoming(sockpath);
} else {
- sharing_fds[0] = tcp_socket_incoming(bindto, port);
+ fd = tcp_socket_incoming(bindto, port);
}
- if (sharing_fds[0] == -1)
+ if (fd == -1) {
return 1;
+ }
if (device) {
int ret;
@@ -514,54 +531,15 @@ int main(int argc, char **argv)
memset(&client_thread, 0, sizeof(client_thread));
}
- max_fd = sharing_fds[0];
- nb_fds++;
+ qemu_init_main_loop();
+ qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL,
+ (void *)(uintptr_t)fd);
do {
- FD_ZERO(&fds);
- FD_SET(sigterm_fd[0], &fds);
- for (i = 0; i < nb_fds; i++)
- FD_SET(sharing_fds[i], &fds);
-
- do {
- ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
- } while (ret == -1 && errno == EINTR);
- if (ret == -1 || FD_ISSET(sigterm_fd[0], &fds)) {
- break;
- }
-
- if (FD_ISSET(sharing_fds[0], &fds))
- ret--;
- for (i = 1; i < nb_fds && ret; i++) {
- if (FD_ISSET(sharing_fds[i], &fds)) {
- if (nbd_trip(exp, sharing_fds[i]) != 0) {
- close(sharing_fds[i]);
- nb_fds--;
- sharing_fds[i] = sharing_fds[nb_fds];
- i--;
- }
- ret--;
- }
- }
- /* new connection ? */
- if (FD_ISSET(sharing_fds[0], &fds)) {
- if (nb_fds < shared + 1) {
- sharing_fds[nb_fds] = accept(sharing_fds[0],
- (struct sockaddr *)&addr,
- &addr_len);
- if (sharing_fds[nb_fds] != -1 &&
- nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) {
- if (sharing_fds[nb_fds] > max_fd)
- max_fd = sharing_fds[nb_fds];
- nb_fds++;
- }
- }
- }
- } while (persistent || nb_fds > 1);
+ main_loop_wait(false);
+ } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0));
- close(sharing_fds[0]);
nbd_export_close(exp);
- g_free(sharing_fds);
if (sockpath) {
unlink(sockpath);
}