[libvirt] [PATCH v7 13/19] utils: Extend virCommandProcessIO to include the send buffers

Stefan Berger stefanb at linux.vnet.ibm.com
Thu Jul 25 18:22:09 UTC 2019


Extend virCommandProcessIO to include the send buffers in the poll
loop.

Signed-off-by: Stefan Berger <stefanb at linux.ibm.com>
Reviewed-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/util/vircommand.c | 62 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 50e14fd8be..cc9fdacc8b 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -1819,6 +1819,61 @@ virCommandSetSendBuffer(virCommandPtr cmd,
 
 #endif
 
+static int
+virCommandSendBuffersFillPollfd(virCommandPtr cmd,
+                                struct pollfd *fds,
+                                int startidx)
+{
+    size_t i, j;
+
+    for (i = 0, j = 0; i < virCommandGetNumSendBuffers(cmd); i++) {
+        if (cmd->sendBuffers[i].fd >= 0) {
+            fds[startidx + j].fd = cmd->sendBuffers[i].fd;
+            fds[startidx + j].events = POLLOUT;
+            fds[startidx + j].revents = 0;
+            j++;
+        }
+    }
+
+    return j;
+}
+
+
+static int
+virCommandSendBuffersHandlePoll(virCommandPtr cmd,
+                                struct pollfd *fds)
+{
+    size_t i;
+    ssize_t done;
+
+    for (i = 0; i < virCommandGetNumSendBuffers(cmd); i++) {
+        if (fds->fd == cmd->sendBuffers[i].fd)
+            break;
+    }
+    if (i == virCommandGetNumSendBuffers(cmd))
+        return 0;
+
+    done = write(fds->fd,
+                 cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset,
+                 cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset);
+    if (done < 0) {
+        if (errno == EPIPE) {
+            VIR_DEBUG("child closed PIPE early, ignoring EPIPE "
+                      "on fd %d", cmd->sendBuffers[i].fd);
+            VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+        } else if (errno != EINTR && errno != EAGAIN) {
+            virReportSystemError(errno, "%s",
+                                 _("unable to write to child input"));
+            return -1;
+        }
+    } else {
+        cmd->sendBuffers[i].offset += done;
+        if (cmd->sendBuffers[i].offset == cmd->sendBuffers[i].buflen)
+            VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+    }
+    return 0;
+}
+
 /**
  * virCommandSetInputBuffer:
  * @cmd: the command to modify
@@ -2173,7 +2228,7 @@ virCommandProcessIO(virCommandPtr cmd)
         goto cleanup;
     ret = -1;
 
-    if (VIR_ALLOC_N(fds, 3) < 0)
+    if (VIR_ALLOC_N(fds, 3 + virCommandGetNumSendBuffers(cmd)) < 0)
         goto cleanup;
 
     for (;;) {
@@ -2199,6 +2254,8 @@ virCommandProcessIO(virCommandPtr cmd)
             nfds++;
         }
 
+        nfds += virCommandSendBuffersFillPollfd(cmd, fds, nfds);
+
         if (nfds == 0)
             break;
 
@@ -2271,6 +2328,9 @@ virCommandProcessIO(virCommandPtr cmd)
                     if (inoff == inlen)
                         VIR_FORCE_CLOSE(cmd->inpipe);
                 }
+            } else if (fds[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
+                if (virCommandSendBuffersHandlePoll(cmd, &fds[i]) < 0)
+                    goto cleanup;
             }
         }
     }
-- 
2.20.1




More information about the libvir-list mailing list