]> xenbits.xensource.com Git - libvirt.git/commitdiff
Merge virCommandPreserveFD / virCommandTransferFD
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 11 Jul 2013 10:31:56 +0000 (11:31 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 18 Jul 2013 11:18:24 +0000 (12:18 +0100)
Merge the virCommandPreserveFD / virCommandTransferFD methods
into a single virCommandPasFD method, and use a new
VIR_COMMAND_PASS_FD_CLOSE_PARENT to indicate their difference
in behaviour

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
docs/internals/command.html.in
src/fdstream.c
src/libvirt_private.syms
src/lxc/lxc_process.c
src/qemu/qemu_command.c
src/uml/uml_conf.c
src/util/vircommand.c
src/util/vircommand.h
tests/commandtest.c

index d63151eeb2f9c30228f03bc49411944f40037638..0336e65c33310413a60779cb41f5821ed9303393 100644 (file)
 <pre>
   int sharedfd = open("cmd.log", "w+");
   int childfd = open("conf.txt", "r");
-  virCommandPreserveFD(cmd, sharedfd);
-  virCommandTransferFD(cmd, childfd);
+  virCommandPassFD(cmd, sharedfd, 0);
+  virCommandPassFD(cmd, childfd,
+                   VIR_COMMAND_PASS_FD_CLOSE_PARENT);
   if (VIR_CLOSE(sharedfd) &lt; 0)
       goto cleanup;
 </pre>
index 2ee9bd8f29f71e96d031e60eb935cdad4d2b43f6..10c7c2af95c194ca4668e53771ce515d21f30c03 100644 (file)
@@ -648,7 +648,8 @@ virFDStreamOpenFileInternal(virStreamPtr st,
                                    path,
                                    NULL);
         virCommandAddArgFormat(cmd, "%llu", length);
-        virCommandTransferFD(cmd, fd);
+        virCommandPassFD(cmd, fd,
+                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
         virCommandAddArgFormat(cmd, "%d", fd);
 
         if ((oflags & O_ACCMODE) == O_RDONLY) {
index fc4e750b536365a40d442da94cc0995660640db5..542424d7df563c46b0739a85601eed66e2abd75b 100644 (file)
@@ -1230,7 +1230,7 @@ virCommandNew;
 virCommandNewArgList;
 virCommandNewArgs;
 virCommandNonblockingFDs;
-virCommandPreserveFD;
+virCommandPassFD;
 virCommandRequireHandshake;
 virCommandRun;
 virCommandRunAsync;
@@ -1251,7 +1251,6 @@ virCommandSetSELinuxLabel;
 virCommandSetUID;
 virCommandSetWorkingDirectory;
 virCommandToString;
-virCommandTransferFD;
 virCommandWait;
 virCommandWriteArgLog;
 virFork;
index b3bbeca140faa84cc2b258cc9b84f7edcdd098c9..54eb728fc38d3f74b71ad06dcba99abee0c4ffc5 100644 (file)
@@ -853,13 +853,13 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
     for (i = 0; i < nttyFDs; i++) {
         virCommandAddArg(cmd, "--console");
         virCommandAddArgFormat(cmd, "%d", ttyFDs[i]);
-        virCommandPreserveFD(cmd, ttyFDs[i]);
+        virCommandPassFD(cmd, ttyFDs[i], 0);
     }
 
     for (i = 0; i < nfiles; i++) {
         virCommandAddArg(cmd, "--passfd");
         virCommandAddArgFormat(cmd, "%d", files[i]);
-        virCommandPreserveFD(cmd, files[i]);
+        virCommandPassFD(cmd, files[i], 0);
     }
 
     virCommandAddArgPair(cmd, "--security",
@@ -873,7 +873,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
         virCommandAddArgList(cmd, "--veth", veths[i], NULL);
     }
 
-    virCommandPreserveFD(cmd, handshakefd);
+    virCommandPassFD(cmd, handshakefd, 0);
 
     return cmd;
 cleanup:
index 71e37f38946822b4d6690201074a5776115f4f80..748cd8fa35389b6b4432265b948b976a8967e35e 100644 (file)
@@ -245,7 +245,8 @@ static int qemuCreateInBridgePortWithHelper(virQEMUDriverConfigPtr cfg,
         virCommandAddArgFormat(cmd, "--use-vnet");
     virCommandAddArgFormat(cmd, "--br=%s", brname);
     virCommandAddArgFormat(cmd, "--fd=%d", pair[1]);
-    virCommandTransferFD(cmd, pair[1]);
+    virCommandPassFD(cmd, pair[1],
+                     VIR_COMMAND_PASS_FD_CLOSE_PARENT);
     virCommandClearCaps(cmd);
 #ifdef CAP_NET_ADMIN
     virCommandAllowCap(cmd, CAP_NET_ADMIN);
@@ -6587,13 +6588,15 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
     }
 
     for (i = 0; i < tapfdSize; i++) {
-        virCommandTransferFD(cmd, tapfd[i]);
+        virCommandPassFD(cmd, tapfd[i],
+                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
         if (virAsprintf(&tapfdName[i], "%d", tapfd[i]) < 0)
             goto cleanup;
     }
 
     for (i = 0; i < vhostfdSize; i++) {
-        virCommandTransferFD(cmd, vhostfd[i]);
+        virCommandPassFD(cmd, vhostfd[i],
+                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
         if (virAsprintf(&vhostfdName[i], "%d", vhostfd[i]) < 0)
             goto cleanup;
     }
@@ -8365,7 +8368,8 @@ qemuBuildCommandLine(virConnectPtr conn,
                             goto error;
                         }
 
-                        virCommandTransferFD(cmd, configfd);
+                        virCommandPassFD(cmd, configfd,
+                                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
                     }
                 }
                 virCommandAddArg(cmd, "-device");
@@ -8431,7 +8435,7 @@ qemuBuildCommandLine(virConnectPtr conn,
         } else if (STREQ(migrateFrom, "stdio")) {
             if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD)) {
                 virCommandAddArgFormat(cmd, "fd:%d", migrateFd);
-                virCommandPreserveFD(cmd, migrateFd);
+                virCommandPassFD(cmd, migrateFd, 0);
             } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) {
                 virCommandAddArg(cmd, "exec:cat");
                 virCommandSetInputFD(cmd, migrateFd);
@@ -8460,7 +8464,7 @@ qemuBuildCommandLine(virConnectPtr conn,
                 goto error;
             }
             virCommandAddArg(cmd, migrateFrom);
-            virCommandPreserveFD(cmd, migrateFd);
+            virCommandPassFD(cmd, migrateFd, 0);
         } else if (STRPREFIX(migrateFrom, "unix")) {
             if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX)) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
index 18cff50569d49fc7a6c212068683afb3fc23d900..0f2f38e5c8fe2d7c3d95be5b5ab8729e538acdeb 100644 (file)
@@ -332,7 +332,8 @@ umlBuildCommandLineChr(virDomainChrDefPtr def,
                 VIR_FORCE_CLOSE(fd_out);
                 return NULL;
             }
-            virCommandTransferFD(cmd, fd_out);
+            virCommandPassFD(cmd, fd_out,
+                             VIR_COMMAND_PASS_FD_CLOSE_PARENT);
         }
         break;
    case VIR_DOMAIN_CHR_TYPE_PIPE:
index 387950401efd28e4aa5f6e74299a4110f861a9d1..00ff69a54e7803ac4cff6237f5c612585e182566 100644 (file)
@@ -64,6 +64,14 @@ enum {
     VIR_EXEC_ASYNC_IO   = (1 << 4),
 };
 
+typedef struct _virCommandFD virCommandFD;
+typedef virCommandFD *virCommandFDPtr;
+
+struct _virCommandFD {
+    int fd;
+    unsigned int flags;
+};
+
 struct _virCommand {
     int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
 
@@ -77,10 +85,8 @@ struct _virCommand {
 
     char *pwd;
 
-    int *preserve; /* FDs to pass to child. */
-    int preserve_size;
-    int *transfer; /* FDs to close in parent. */
-    int transfer_size;
+    size_t npassfd;
+    virCommandFDPtr passfd;
 
     unsigned int flags;
 
@@ -135,14 +141,15 @@ struct _virCommand {
  * false otherwise.
  */
 static bool
-virCommandFDIsSet(int fd,
-                  const int *set,
-                  int set_size)
+virCommandFDIsSet(virCommandPtr cmd,
+                  int fd)
 {
     size_t i = 0;
+    if (!cmd)
+        return false;
 
-    while (i < set_size)
-        if (set[i++] == fd)
+    while (i < cmd->npassfd)
+        if (cmd->passfd[i++].fd == fd)
             return true;
 
     return false;
@@ -163,22 +170,21 @@ virCommandFDIsSet(int fd,
  *          ENOMEM on OOM
  */
 static int
-virCommandFDSet(int fd,
-                int **set,
-                int *set_size)
+virCommandFDSet(virCommandPtr cmd,
+                int fd,
+                unsigned int flags)
 {
-    if (fd < 0 || !set || !set_size)
+    if (!cmd || fd < 0)
         return -1;
 
-    if (virCommandFDIsSet(fd, *set, *set_size))
+    if (virCommandFDIsSet(cmd, fd))
         return 0;
 
-    if (VIR_REALLOC_N(*set, *set_size + 1) < 0) {
+    if (VIR_EXPAND_N(cmd->passfd, cmd->npassfd, 1) < 0)
         return ENOMEM;
-    }
 
-    (*set)[*set_size] = fd;
-    (*set_size)++;
+    cmd->passfd[cmd->npassfd - 1].fd = fd;
+    cmd->passfd[cmd->npassfd - 1].flags = flags;
 
     return 0;
 }
@@ -525,8 +531,7 @@ virExec(virCommandPtr cmd)
     for (fd = 3; fd < openmax; fd++) {
         if (fd == childin || fd == childout || fd == childerr)
             continue;
-        if (!cmd->preserve ||
-            !virCommandFDIsSet(fd, cmd->preserve, cmd->preserve_size)) {
+        if (!virCommandFDIsSet(cmd, fd)) {
             tmpfd = fd;
             VIR_MASS_CLOSE(tmpfd);
         } else if (virSetInherit(fd, true) < 0) {
@@ -882,67 +887,51 @@ virCommandNewVAList(const char *binary, va_list list)
 }
 
 
-/*
- * Preserve the specified file descriptor in the child, instead of
- * closing it.  FD must not be one of the three standard streams.  If
- * transfer is true, then fd will be closed in the parent after a call
- * to Run/RunAsync/Free, otherwise caller is still responsible for fd.
- * Returns true if a transferring caller should close FD now, and
- * false if the transfer is successfully recorded.
- */
-static bool
-virCommandKeepFD(virCommandPtr cmd, int fd, bool transfer)
-{
-    int ret = 0;
-
-    if (!cmd)
-        return fd > STDERR_FILENO;
-
-    if (fd <= STDERR_FILENO ||
-        (ret = virCommandFDSet(fd, &cmd->preserve, &cmd->preserve_size)) ||
-        (transfer && (ret = virCommandFDSet(fd, &cmd->transfer,
-                                            &cmd->transfer_size)))) {
-        if (!cmd->has_error)
-            cmd->has_error = ret ? ret : -1;
-        VIR_DEBUG("cannot preserve %d", fd);
-        return fd > STDERR_FILENO;
-    }
-
-    return false;
-}
-
-/**
- * virCommandPreserveFD:
- * @cmd: the command to modify
- * @fd: fd to mark for inheritance into child
- *
- * Preserve the specified file descriptor
- * in the child, instead of closing it on exec.
- * The parent is still responsible for managing fd.
- */
-void
-virCommandPreserveFD(virCommandPtr cmd, int fd)
-{
-    virCommandKeepFD(cmd, fd, false);
-}
+#define VIR_COMMAND_MAYBE_CLOSE_FD(fd, flags)       \
+    if ((fd > STDERR_FILENO) &&                     \
+        (flags & VIR_COMMAND_PASS_FD_CLOSE_PARENT)) \
+        VIR_FORCE_CLOSE(fd)
 
 /**
- * virCommandTransferFD:
+ * virCommandPassFD:
  * @cmd: the command to modify
  * @fd: fd to reassign to the child
+ * @flags: the flags
  *
- * Transfer the specified file descriptor
- * to the child, instead of closing it on exec.
- * The parent should no longer use fd, and the parent's copy will
- * be automatically closed no later than during Run/RunAsync/Free.
+ * Transfer the specified file descriptor to the child, instead
+ * of closing it on exec. @fd must not be one of the three
+ * standard streams.
+ *
+ * If the flag VIR_COMMAND_PASS_FD_CLOSE_PARENT is set then fd will
+ * be closed in the parent no later than Run/RunAsync/Free. The parent
+ * should cease using the @fd when this call completes
  */
 void
-virCommandTransferFD(virCommandPtr cmd, int fd)
+virCommandPassFD(virCommandPtr cmd, int fd, unsigned int flags)
 {
-    if (virCommandKeepFD(cmd, fd, true))
-        VIR_FORCE_CLOSE(fd);
-}
+    int ret = 0;
+
+    if (!cmd) {
+        VIR_COMMAND_MAYBE_CLOSE_FD(fd, flags);
+        return;
+    }
+
+    if (fd <= STDERR_FILENO) {
+        VIR_DEBUG("invalid fd %d", fd);
+        VIR_COMMAND_MAYBE_CLOSE_FD(fd, flags);
+        if (!cmd->has_error)
+            cmd->has_error = -1;
+        return;
+    }
 
+    if ((ret = virCommandFDSet(cmd, fd, flags)) != 0) {
+        if (!cmd->has_error)
+            cmd->has_error = ret;
+        VIR_DEBUG("cannot preserve %d", fd);
+        VIR_COMMAND_MAYBE_CLOSE_FD(fd, flags);
+        return;
+    }
+}
 
 /**
  * virCommandSetPidFile:
@@ -2252,11 +2241,12 @@ virCommandRunAsync(virCommandPtr cmd, pid_t *pid)
     VIR_DEBUG("Command result %d, with PID %d",
               ret, (int)cmd->pid);
 
-    for (i = 0; i < cmd->transfer_size; i++) {
-        VIR_FORCE_CLOSE(cmd->transfer[i]);
+    for (i = 0; i < cmd->npassfd; i++) {
+        if (cmd->passfd[i].flags & VIR_COMMAND_PASS_FD_CLOSE_PARENT)
+            VIR_FORCE_CLOSE(cmd->passfd[i].fd);
     }
-    cmd->transfer_size = 0;
-    VIR_FREE(cmd->transfer);
+    cmd->npassfd = 0;
+    VIR_FREE(cmd->passfd);
 
     if (ret == 0 && pid)
         *pid = cmd->pid;
@@ -2431,8 +2421,10 @@ void virCommandRequireHandshake(virCommandPtr cmd)
               "keep handshake wait=%d notify=%d",
               cmd->handshakeWait[1], cmd->handshakeNotify[0],
               cmd->handshakeWait[0], cmd->handshakeNotify[1]);
-    virCommandTransferFD(cmd, cmd->handshakeWait[1]);
-    virCommandTransferFD(cmd, cmd->handshakeNotify[0]);
+    virCommandPassFD(cmd, cmd->handshakeWait[1],
+                     VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+    virCommandPassFD(cmd, cmd->handshakeNotify[0],
+                     VIR_COMMAND_PASS_FD_CLOSE_PARENT);
     cmd->handshake = true;
 }
 
@@ -2555,9 +2547,12 @@ virCommandFree(virCommandPtr cmd)
     if (!cmd)
         return;
 
-    for (i = 0; i < cmd->transfer_size; i++) {
-        VIR_FORCE_CLOSE(cmd->transfer[i]);
+    for (i = 0; i < cmd->npassfd; i++) {
+        if (cmd->passfd[i].flags & VIR_COMMAND_PASS_FD_CLOSE_PARENT)
+            VIR_FORCE_CLOSE(cmd->passfd[i].fd);
     }
+    cmd->npassfd = 0;
+    VIR_FREE(cmd->passfd);
 
     if (cmd->asyncioThread) {
         virThreadJoin(cmd->asyncioThread);
@@ -2579,7 +2574,7 @@ virCommandFree(virCommandPtr cmd)
 
     if (cmd->handshake) {
         /* The other 2 fds in these arrays are closed
-         * due to use with virCommandTransferFD
+         * due to use with virCommandPassFD
          */
         VIR_FORCE_CLOSE(cmd->handshakeWait[0]);
         VIR_FORCE_CLOSE(cmd->handshakeNotify[1]);
@@ -2590,8 +2585,6 @@ virCommandFree(virCommandPtr cmd)
     if (cmd->reap)
         virCommandAbort(cmd);
 
-    VIR_FREE(cmd->transfer);
-    VIR_FREE(cmd->preserve);
 #if defined(WITH_SECDRIVER_SELINUX)
     VIR_FREE(cmd->seLinuxLabel);
 #endif
index a4021392d13da79fa62a0b942369fe62ae3721f9..c619e0644facea8a213935dbed1a47c5c6957ec2 100644 (file)
@@ -51,11 +51,14 @@ virCommandPtr virCommandNewVAList(const char *binary, va_list list)
  * delayed until the Run/RunAsync methods
  */
 
-void virCommandPreserveFD(virCommandPtr cmd,
-                          int fd);
-
-void virCommandTransferFD(virCommandPtr cmd,
-                          int fd);
+enum {
+    /* Close the FD in the parent */
+    VIR_COMMAND_PASS_FD_CLOSE_PARENT = (1 << 0),
+};
+
+void virCommandPassFD(virCommandPtr cmd,
+                      int fd,
+                      unsigned int flags);
 
 void virCommandSetPidFile(virCommandPtr cmd,
                           const char *pidfile) ATTRIBUTE_NONNULL(2);
index 62f0277df7eae939985d96bebd19be2893953354..eeb6d1e131694eccc29c5b03ec7b641eb0f7de54 100644 (file)
@@ -194,8 +194,9 @@ static int test3(const void *unused ATTRIBUTE_UNUSED)
     int newfd3 = dup(STDERR_FILENO);
     int ret = -1;
 
-    virCommandPreserveFD(cmd, newfd1);
-    virCommandTransferFD(cmd, newfd3);
+    virCommandPassFD(cmd, newfd1, 0);
+    virCommandPassFD(cmd, newfd3,
+                     VIR_COMMAND_PASS_FD_CLOSE_PARENT);
 
     if (virCommandRun(cmd, NULL) < 0) {
         virErrorPtr err = virGetLastError();