qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v5] qemu-config: Add new -add-fd command line op


From: Corey Bryant
Subject: Re: [Qemu-devel] [PATCH v5] qemu-config: Add new -add-fd command line option
Date: Mon, 22 Oct 2012 11:06:59 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121009 Thunderbird/16.0



On 10/22/2012 10:36 AM, Kevin Wolf wrote:
From: Corey Bryant <address@hidden>

This option can be used for passing file descriptors on the
command line.  It mirrors the existing add-fd QMP command which
allows an fd to be passed to QEMU via SCM_RIGHTS and added to an
fd set.

This can be combined with commands such as -drive to link file
descriptors in an fd set to a drive:

     qemu-kvm -add-fd fd=3,set=2,opaque="rdwr:/path/to/file"
              -add-fd fd=4,set=2,opaque="rdonly:/path/to/file"
              -drive file=/dev/fdset/2,index=0,media=disk

This example adds dups of fds 3 and 4, and the accompanying opaque
strings to the fd set with ID=2.  qemu_open() already knows how
to handle a filename of this format.  qemu_open() searches the
corresponding fd set for an fd and when it finds a match, QEMU
goes on to use a dup of that fd just like it would have used an
fd that it opened itself.

Signed-off-by: Corey Bryant <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---

Sorry, Corey, hope you're okay with me taking over your patch... Your patch was
against the unmodified version while I already did some changes after the v4
review, so it didn't apply.


That's fine.  Thanks for the hand.

This version just completely disables fd passing on Windows as I don't think
it works there anyway. Gives you a nice error message instead of a silently
ignored -add-fd option.

Also added the missing break for case QEMU_OPTION_add_fd.

  qemu-config.c   |   22 +++++++++++++
  qemu-options.hx |   36 +++++++++++++++++++++
  vl.c            |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 152 insertions(+), 0 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index cd1ec21..601237d 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -653,6 +653,27 @@ QemuOptsList qemu_boot_opts = {
      },
  };

+static QemuOptsList qemu_add_fd_opts = {
+    .name = "add-fd",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_add_fd_opts.head),
+    .desc = {
+        {
+            .name = "fd",
+            .type = QEMU_OPT_NUMBER,
+            .help = "file descriptor of which a duplicate is added to fd set",
+        },{
+            .name = "set",
+            .type = QEMU_OPT_NUMBER,
+            .help = "ID of the fd set to add fd to",
+        },{
+            .name = "opaque",
+            .type = QEMU_OPT_STRING,
+            .help = "free-form string used to describe fd",
+        },
+        { /* end of list */ }
+    },
+};
+
  static QemuOptsList *vm_config_groups[32] = {
      &qemu_drive_opts,
      &qemu_chardev_opts,
@@ -669,6 +690,7 @@ static QemuOptsList *vm_config_groups[32] = {
      &qemu_boot_opts,
      &qemu_iscsi_opts,
      &qemu_sandbox_opts,
+    &qemu_add_fd_opts,
      NULL,
  };

diff --git a/qemu-options.hx b/qemu-options.hx
index 46f0539..a67a255 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -253,6 +253,14 @@ qemu-system-i386 -drive file=file,index=2,media=disk
  qemu-system-i386 -drive file=file,index=3,media=disk
  @end example

+You can open an image using pre-opened file descriptors from an fd set:
address@hidden
+qemu-system-i386
+-add-fd fd=3,set=2,opaque="rdwr:/path/to/file"
+-add-fd fd=4,set=2,opaque="rdonly:/path/to/file"
+-drive file=/dev/fdset/2,index=0,media=disk
address@hidden example
+
  You can connect a CDROM to the slave of ide0:
  @example
  qemu-system-i386 -drive file=file,if=ide,index=1,media=cdrom
@@ -285,6 +293,34 @@ qemu-system-i386 -hda a -hdb b
  @end example
  ETEXI

+DEF("add-fd", HAS_ARG, QEMU_OPTION_add_fd,
+    "-add-fd fd=fd,set=set[,opaque=opaque]\n"
+    "                Add 'fd' to fd 'set'\n", QEMU_ARCH_ALL)
+STEXI
address@hidden -add-fd address@hidden,address@hidden,address@hidden
address@hidden -add-fd
+
+Add a file descriptor to an fd set.  Valid options are:
+
address@hidden @option
address@hidden address@hidden
+This option defines the file descriptor of which a duplicate is added to fd 
set.
+The file descriptor cannot be stdin, stdout, or stderr.
address@hidden address@hidden
+This option defines the ID of the fd set to add the file descriptor to.
address@hidden address@hidden
+This option defines a free-form string that can be used to describe @var{fd}.
address@hidden table
+
+You can open an image using pre-opened file descriptors from an fd set:
address@hidden
+qemu-system-i386
+-add-fd fd=3,set=2,opaque="rdwr:/path/to/file"
+-add-fd fd=4,set=2,opaque="rdonly:/path/to/file"
+-drive file=/dev/fdset/2,index=0,media=disk
address@hidden example
+ETEXI
+
  DEF("set", HAS_ARG, QEMU_OPTION_set,
      "-set group.id.arg=value\n"
      "                set <arg> parameter for item <id> of type <group>\n"
diff --git a/vl.c b/vl.c
index ee3c43a..b870caf 100644
--- a/vl.c
+++ b/vl.c
@@ -790,6 +790,78 @@ static int parse_sandbox(QemuOpts *opts, void *opaque)
      return 0;
  }

+#ifndef _WIN32
+static int parse_add_fd(QemuOpts *opts, void *opaque)
+{
+    int fd, dupfd, flags;
+    int64_t fdset_id;
+    const char *fd_opaque = NULL;
+
+    fd = qemu_opt_get_number(opts, "fd", -1);
+    fdset_id = qemu_opt_get_number(opts, "set", -1);
+    fd_opaque = qemu_opt_get(opts, "opaque");
+
+    if (fd < 0) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "fd option is required and must be non-negative");
+        return -1;
+    }
+
+    if (fd <= STDERR_FILENO) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "fd cannot be a standard I/O stream");
+        return -1;
+    }
+
+    /*
+     * All fds inherited across exec() necessarily have FD_CLOEXEC
+     * clear, while qemu sets FD_CLOEXEC on all other fds used internally.
+     */
+    flags = fcntl(fd, F_GETFD);
+    if (flags == -1 || (flags & FD_CLOEXEC)) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "fd is not valid or already in use");
+        return -1;
+    }
+
+    if (fdset_id < 0) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "set option is required and must be non-negative");
+        return -1;
+    }
+
+#ifdef F_DUPFD_CLOEXEC
+    dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+#else
+    dupfd = dup(fd);
+    if (dupfd != -1) {
+        qemu_set_cloexec(dupfd);
+    }
+#endif
+    if (dupfd == -1) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "Error duplicating fd: %s", strerror(errno));
+        return -1;
+    }
+
+    /* add the duplicate fd, and optionally the opaque string, to the fd set */
+    monitor_fdset_add_fd(dupfd, true, fdset_id, fd_opaque ? true : false,
+                         fd_opaque, NULL);
+
+    return 0;
+}
+
+static int cleanup_add_fd(QemuOpts *opts, void *opaque)
+{
+    int fd;
+
+    fd = qemu_opt_get_number(opts, "fd", -1);
+    close(fd);
+
+    return 0;
+}
+#endif
+
  /***********************************************************/
  /* QEMU Block devices */

@@ -3309,6 +3381,18 @@ int main(int argc, char **argv, char **envp)
                      exit(0);
                  }
                  break;
+            case QEMU_OPTION_add_fd:
+#ifndef _WIN32
+                opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0);
+                if (!opts) {
+                    exit(0);
+                }
+#else
+                error_report("File descriptor passing is disabled on this "
+                             "platform");
+                exit(1);
+#endif
+                break;
              default:
                  os_parse_cmd_args(popt->index, optarg);
              }
@@ -3320,6 +3404,16 @@ int main(int argc, char **argv, char **envp)
          exit(1);
      }

+#ifndef _WIN32
+    if (qemu_opts_foreach(qemu_find_opts("add-fd"), parse_add_fd, NULL, 1)) {
+        exit(1);
+    }
+
+    if (qemu_opts_foreach(qemu_find_opts("add-fd"), cleanup_add_fd, NULL, 1)) {
+        exit(1);
+    }
+#endif
+
      if (machine == NULL) {
          fprintf(stderr, "No machine found.\n");
          exit(1);


This looks good to me.

--
Regards,
Corey Bryant




reply via email to

[Prev in Thread] Current Thread [Next in Thread]