From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:37839) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SPFGY-0006PV-4V for qemu-devel@nongnu.org; Tue, 01 May 2012 11:45:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SPFGQ-0005xb-TL for qemu-devel@nongnu.org; Tue, 01 May 2012 11:45:25 -0400 Received: from e06smtp10.uk.ibm.com ([195.75.94.106]:55916) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SPF44-0001G0-3g for qemu-devel@nongnu.org; Tue, 01 May 2012 11:32:32 -0400 Received: from /spool/local by e06smtp10.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 1 May 2012 16:32:27 +0100 Received: from d06av12.portsmouth.uk.ibm.com (d06av12.portsmouth.uk.ibm.com [9.149.37.247]) by d06nrmr1806.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q41FW03n594092 for ; Tue, 1 May 2012 16:32:00 +0100 Received: from d06av12.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av12.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q41FW0qM019033 for ; Tue, 1 May 2012 09:32:00 -0600 From: Stefan Hajnoczi Date: Tue, 1 May 2012 16:31:45 +0100 Message-Id: <1335886307-27586-4-git-send-email-stefanha@linux.vnet.ibm.com> In-Reply-To: <1335886307-27586-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1335886307-27586-1-git-send-email-stefanha@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC 3/5] block: plumb up open-hook-fd option List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Anthony Liguori , Stefan Hajnoczi , libvir-list@redhat.com, Corey Bryant From: Anthony Liguori Implement the open hook UNIX domain socket protocol and accept passed file descriptors. Signed-off-by: Anthony Liguori Signed-off-by: Stefan Hajnoczi --- block.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++- block.h | 2 + block/raw-posix.c | 2 +- qemu-options.hx | 4 +- vl.c | 3 ++ 5 files changed, 114 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index f9c4633..d3bf443 100644 --- a/block.c +++ b/block.c @@ -31,6 +31,7 @@ #include "qemu-coroutine.h" #include "qmp-commands.h" #include "qemu-timer.h" +#include "qemu_socket.h" #ifdef CONFIG_BSD #include @@ -102,9 +103,113 @@ static BlockDriverState *bs_snapshots; /* If non-zero, use only whitelisted block drivers */ static int use_bdrv_whitelist; +static int remote_file_fd = -1; + +void remote_file_open_init(int fd) +{ + remote_file_fd = fd; +} + +typedef struct OpenRequest +{ + uint32_t message_len; + uint32_t type; + uint32_t flags; + uint32_t mode; + uint32_t filename_len; + uint8_t filename[0]; +} OpenRequest; + +typedef struct OpenResponse +{ + uint32_t message_len; + uint32_t type; + int32_t result; +} OpenResponse; + int file_open(const char *filename, int flags, mode_t mode) { - return open(filename, flags, mode); +#ifdef _WIN32 + return qemu_open(filename, flags, mode); +#else + struct msghdr msg = { NULL, }; + struct cmsghdr *cmsg; + struct iovec iov[1]; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(int))]; + } msg_control; + ssize_t ret; + uint8_t buffer[1024]; + OpenRequest *req = (void *)buffer; + OpenResponse *rsp = (void *)buffer; + + if (remote_file_fd == -1) { + return qemu_open(filename, flags, mode); + } + + req->filename_len = strlen(filename); + req->message_len = sizeof(OpenRequest) + req->filename_len; + req->type = 1; /* OpenRequest */ + req->flags = flags; + req->mode = mode; + + if (req->message_len > sizeof(buffer)) { + errno = EFAULT; + return -1; + } + memcpy(req->filename, filename, req->filename_len); + + do { + ret = send(remote_file_fd, req, req->message_len, 0); + } while (ret == -1 && errno == EINTR); + if (ret != req->message_len) { + errno = EPIPE; + return -1; + } + + iov[0].iov_base = buffer; + iov[0].iov_len = sizeof(buffer); + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); + + do { + ret = recvmsg(remote_file_fd, &msg, 0); + } while (ret == -1 && errno == EINTR); + if (ret != sizeof(OpenResponse)) { + errno = EPIPE; + return -1; + } + + rsp = (void *)buffer; + if (rsp->result < 0) { + errno = -rsp->result; + return -1; + } + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + int fd; + + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + continue; + } + + fd = *((int *)CMSG_DATA(cmsg)); + if (fd < 0) { + continue; + } + + return fd; + } + + errno = ENOENT; + return -1; +#endif } #ifdef _WIN32 diff --git a/block.h b/block.h index f163e54..b8b78c7 100644 --- a/block.h +++ b/block.h @@ -336,6 +336,8 @@ int bdrv_img_create(const char *filename, const char *fmt, void bdrv_set_buffer_alignment(BlockDriverState *bs, int align); void *qemu_blockalign(BlockDriverState *bs, size_t size); +void remote_file_open_init(int fd); + #define BDRV_SECTORS_PER_DIRTY_CHUNK 2048 void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable); diff --git a/block/raw-posix.c b/block/raw-posix.c index b6bc6bc..9946e5f 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -208,7 +208,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, s->open_flags |= O_DSYNC; s->fd = -1; - fd = qemu_open(filename, s->open_flags, 0644); + fd = file_open(filename, s->open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) diff --git a/qemu-options.hx b/qemu-options.hx index ccf4d1d..0c54cd5 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2730,8 +2730,8 @@ DEF("open-hook-fd", HAS_ARG, QEMU_OPTION_open_hook_fd, STEXI @item -open-hook-fd @var{fd} @findex -open-hook-fd -Delegates open()s to an external process using @var to communicate commands. -@var should be an open Unix Domain socket pipe that file descriptors can be +Delegates open()s to an external process using @var{fd} to communicate commands. +@var{fd} should be an open Unix Domain socket pipe that file descriptors can be received from. The protocol the socket uses is a simple request/response initiated by the client. All integers are in host byte order. It is assumed that this protocol is only ever used on the same physical machine. It is currently defined as: diff --git a/vl.c b/vl.c index ae91a8a..b418865 100644 --- a/vl.c +++ b/vl.c @@ -3191,6 +3191,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_qtest_log: qtest_log = optarg; break; + case QEMU_OPTION_open_hook_fd: + remote_file_open_init(atoi(optarg)); + break; default: os_parse_cmd_args(popt->index, optarg); } -- 1.7.10