From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:57037) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWZ5s-0006yP-Un for qemu-devel@nongnu.org; Mon, 21 May 2012 16:20:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SWZ5o-0004KB-DO for qemu-devel@nongnu.org; Mon, 21 May 2012 16:20:40 -0400 Received: from e3.ny.us.ibm.com ([32.97.182.143]:41422) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWZ5o-0004JJ-74 for qemu-devel@nongnu.org; Mon, 21 May 2012 16:20:36 -0400 Received: from /spool/local by e3.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 21 May 2012 16:20:29 -0400 Received: from d01relay04.pok.ibm.com (d01relay04.pok.ibm.com [9.56.227.236]) by d01dlp01.pok.ibm.com (Postfix) with ESMTP id E538938C805E for ; Mon, 21 May 2012 16:20:06 -0400 (EDT) Received: from d03av03.boulder.ibm.com (d03av03.boulder.ibm.com [9.17.195.169]) by d01relay04.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q4LKK6HY121752 for ; Mon, 21 May 2012 16:20:07 -0400 Received: from d03av03.boulder.ibm.com (loopback [127.0.0.1]) by d03av03.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q4LKK6B4004315 for ; Mon, 21 May 2012 14:20:06 -0600 From: Corey Bryant Date: Mon, 21 May 2012 16:19:58 -0400 Message-Id: <1337631598-30639-5-git-send-email-coreyb@linux.vnet.ibm.com> In-Reply-To: <1337631598-30639-1-git-send-email-coreyb@linux.vnet.ibm.com> References: <1337631598-30639-1-git-send-email-coreyb@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC PATCH 4/4] Example -filefd and getfd_file server List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@linux.vnet.ibm.com, libvir-list@redhat.com, eblake@redhat.com This example demonstrates use of the -filefd command to open two disk drives at start-up time. It also demonstrates hot attaching a third disk drive with the getfd_file monitor command. I still have some learning to do with regards to QMP, so the example is using a not-so-program-friendly HMP method. Usage: ./test-fd-passing /path/hda.img /path/hdb.img /path/hdc.img Signed-off-by: Corey Bryant --- test-fd-passing.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 224 insertions(+), 0 deletions(-) create mode 100644 test-fd-passing.c diff --git a/test-fd-passing.c b/test-fd-passing.c new file mode 100644 index 0000000..d568198 --- /dev/null +++ b/test-fd-passing.c @@ -0,0 +1,224 @@ +/* + * QEMU -filefd and getfd_file test server + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Stefan Hajnoczi + * Corey Bryant + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + * gcc -Wall -o test-fd-passing test-fd-passing.c + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int openQemuMonitor(const char *monitor) +{ + int i; + int ret; + struct sockaddr_un addr; + int monfd = 0; + + if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("socket"); + goto error; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, monitor); + + for (i = 0; i < 100; i++) { + ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr)); + if (ret == 0) { + break; + } + usleep(.2 * 1000000); + } + + if (ret != 0) { + fprintf(stderr, "no monitor socket"); + goto error; + } + + return monfd; + +error: + close(monfd); + return -1; +} + +static int issueHMPCmdFD(int monfd,const char *data, size_t len, int fd) +{ + int ret; + struct msghdr msg; + struct iovec iov[1]; + char control[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; + + memset(&msg, 0, sizeof(msg)); + + iov[0].iov_base = (void *)data; + iov[0].iov_len = len; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + + do { + ret = sendmsg(monfd, &msg, 0); + } while (ret < 0 && errno == EINTR); + + return ret; +} + +int main(int argc, char *argv[]) { + int rc; + int fd1, fd2, hotfd, monfd=-1; + int flags = O_RDWR; + int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + pid_t child_pid; + char *drive_str_1 = NULL;; + char *drive_str_2 = NULL;; + char *filefd_str_1 = NULL; + char *filefd_str_2 = NULL; + char *getfd_file_str = NULL; + char *drive_add_str = NULL; + char *device_add_str = NULL; + + if (argc != 4) { + fprintf(stderr, "usage: %s \n", argv[0]); + goto error; + } + + fd1 = open(argv[1], flags, mode); + if (fd1 == -1) { + perror("open"); + goto error; + } + + fd2 = open(argv[2], flags, mode); + if (fd2 == -1) { + perror("open"); + goto error; + } + + hotfd = open(argv[3], flags, mode); + if (hotfd == -1) { + perror("open"); + goto error; + } + + asprintf(&drive_str_1, "file=%s,if=none,id=drive-virtio-disk0", argv[1]); + asprintf(&filefd_str_1, "file=%s,fd=%d", argv[1], fd1); + asprintf(&drive_str_2, "file=%s,if=none,id=drive-virtio-disk1", argv[2]); + asprintf(&filefd_str_2, "file=%s,fd=%d", argv[2], fd2); + + char *child_argv[] = { + "qemu-system-x86_64", + "-enable-kvm", + "-m", "1024", + "-chardev", + "socket,id=charmonitor,path=/var/lib/libvirt/qemu/RHEL62.monitor,server,nowait", + "-mon", + "chardev=charmonitor,id=monitor,mode=readline", + "-drive", drive_str_1, + "-device", + "virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0", + "-drive", drive_str_2, + "-device", + "virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk1", + "-filefd", filefd_str_1, + "-filefd", filefd_str_2, + "-vnc", ":0", + NULL, + }; + + if (posix_spawn(&child_pid, "/usr/local/bin/qemu-system-x86_64", + NULL, NULL, child_argv, environ) != 0) { + perror("posix_spawn\n"); + goto error; + } + + monfd = openQemuMonitor("/var/lib/libvirt/qemu/RHEL62.monitor"); + if (monfd == -1) { + goto error; + } + + asprintf(&getfd_file_str, "getfd_file %s\r\n", argv[3]); + rc = issueHMPCmdFD(monfd, getfd_file_str, + strlen(getfd_file_str), hotfd); + if (rc < 0) { + perror("issueHMPCmdFD"); + goto error; + } + + sleep(1); + asprintf(&drive_add_str, "drive_add data_drive file=%s,%s", argv[3], + "if=none,id=drive-virtio-disk2,cache=writethrough\r\n"); + rc = write(monfd, drive_add_str, strlen(drive_add_str)); + if (rc < 0) { + perror("write"); + goto error; + } + + sleep(1); + asprintf(&device_add_str, "device_add virtio-blk-pci,bus=pci.0,%s", + "addr=0x8,drive=drive-virtio-disk2,id=virtio-disk2\r\n"); + rc = write(monfd, device_add_str, strlen(device_add_str)); + if (rc < 0) { + perror("write"); + goto error; + } + +error: + if (drive_str_1) { + free(drive_str_1); + } + if (drive_str_2) { + free(drive_str_2); + } + if (filefd_str_1) { + free(filefd_str_1); + } + if (filefd_str_2) { + free(filefd_str_2); + } + if (getfd_file_str) { + free(getfd_file_str); + } + if (drive_add_str) { + free(drive_add_str); + } + if (device_add_str) { + free(device_add_str); + } + if (monfd != -1) { + close(monfd); + } + return -1; +} -- 1.7.7.6