From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50078) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xkx3G-0002ld-Ia for qemu-devel@nongnu.org; Sun, 02 Nov 2014 10:26:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xkx39-0008QF-N3 for qemu-devel@nongnu.org; Sun, 02 Nov 2014 10:26:46 -0500 Received: from mail-pa0-x235.google.com ([2607:f8b0:400e:c03::235]:59968) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xkx39-0008Q7-Bl for qemu-devel@nongnu.org; Sun, 02 Nov 2014 10:26:39 -0500 Received: by mail-pa0-f53.google.com with SMTP id kx10so10650590pab.40 for ; Sun, 02 Nov 2014 07:26:38 -0800 (PST) From: Jun Sheng Date: Sun, 2 Nov 2014 23:26:52 +0800 Message-Id: <1414942012-5242-1-git-send-email-chaoseternal@gmail.com> Subject: [Qemu-devel] [PATCH][v2] inetd enabled qemu-nbd List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Jun Sheng run qemu-nbd as an inetd service has some benefits * more scriptable, such as serve multiple images to different clients on one ip/port * access control using tcpd simple usage: #!/bin/sh # qemu-nbd wrapper, select image file according to client ip address IMG_FILE=`sed -n "s/$REMOTE_HOST //p" /path/to/image_list.txt` qemu-nbd -i 10 $IMG_FILE 10<&0- 1>/tmp/log 2>/tmp/log2 #end #xinetd.conf service nbd { flags = REUSE socket_type = stream wait = no user = some_user server = /path/to/qemu-nbd-wrapper.sh log_on_failure += USERID disable = no } Signed-off-by: Jun Sheng --- qemu-nbd.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index 5cd6c6d..f4af4c7 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -49,6 +49,7 @@ static NBDExport *exp; static int verbose; static char *srcpath; static char *sockpath; +static int inetd_fd = -1; static int persistent = 0; static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state; static int shared = 1; @@ -66,6 +67,7 @@ static void usage(const char *name) "Connection properties:\n" " -p, --port=PORT port to listen on (default `%d')\n" " -b, --bind=IFACE interface to bind to (default `0.0.0.0')\n" +" -i, --inetd=FD run as an inetd services on FD\n" " -k, --socket=PATH path to the unix socket\n" " (default '"SOCKET_PATH"')\n" " -e, --shared=NUM device can be shared by NUM clients (default '1')\n" @@ -363,7 +365,13 @@ static void nbd_accept(void *opaque) struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); - int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); + int fd; + if (inetd_fd < 0) { + fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); + } else { + fd = server_fd; + } + if (fd < 0) { perror("accept"); return; @@ -396,10 +404,11 @@ int main(int argc, char **argv) off_t fd_size; QemuOpts *sn_opts = NULL; const char *sn_id_or_name = NULL; - const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:"; + const char *sopt = "hVi:b:o:p:rsnP:c:dvk:e:f:tl:"; struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, + { "inetd", 1, NULL, 'i'}, { "bind", 1, NULL, 'b' }, { "port", 1, NULL, 'p' }, { "socket", 1, NULL, 'k' }, @@ -508,6 +517,16 @@ int main(int argc, char **argv) "without setting discard operation to unmap"); } break; + case 'i': + inetd_fd = qemu_parse_fd(optarg); + if (inetd_fd < 0) { + errx(EXIT_FAILURE, "Invalid inet fd `%s'", optarg); + } + if (inetd_fd <= STDERR_FILENO) { + errx(EXIT_FAILURE, "Inet fd out of range `%s'," + " should be in [3, 65535]", optarg); + } + break; case 'b': bindto = optarg; break; @@ -732,10 +751,14 @@ int main(int argc, char **argv) exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed); - if (sockpath) { - fd = unix_socket_incoming(sockpath); + if (inetd_fd < 0) { + if (sockpath) { + fd = unix_socket_incoming(sockpath); + } else { + fd = tcp_socket_incoming(bindto, port); + } } else { - fd = tcp_socket_incoming(bindto, port); + fd = inetd_fd; } if (fd < 0) { @@ -754,9 +777,12 @@ int main(int argc, char **argv) /* Shut up GCC warnings. */ memset(&client_thread, 0, sizeof(client_thread)); } - - qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL, - (void *)(uintptr_t)fd); + if (inetd_fd < 0) { + qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL, + (void *)(uintptr_t)fd); + } else { + nbd_accept((void *)(uintptr_t)fd); + } /* now when the initialization is (almost) complete, chdir("/") * to free any busy filesystems */ -- 2.1.2