[libvirt] [PATCH v3 16/21] utils: Extend virCommandProcessIO to include the send buffers

Stefan Berger stefanb at linux.vnet.ibm.com
Wed Jul 10 21:08:54 UTC 2019


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

Signed-off-by: Stefan Berger <stefanb at linux.ibm.com>
---
 src/util/vircommand.c | 70 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 0e367eeeab..bb11a76118 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -1803,6 +1803,69 @@ virCommandSetSendBuffer(virCommandPtr cmd,
 }
 
 
+static int
+virCommandGetNumSendBuffers(virCommandPtr cmd)
+{
+    return cmd->numSendBuffers;
+}
+
+
+static int
+virCommandSendBuffersFillPollfd(virCommandPtr cmd,
+                                struct pollfd *fds,
+                                int startidx)
+{
+    size_t i, j;
+
+    for (i = 0, j = 0; i < cmd->numSendBuffers; 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;
+    int done;
+
+    for (i = 0; i < cmd->numSendBuffers; i++) {
+        if (fds->fd == cmd->sendBuffers[i].fd)
+            break;
+    }
+    if (i == cmd->numSendBuffers)
+        return 0;
+
+    done = write(fds->fd,
+                 cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset,
+                 MIN(cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset,
+                     MAX_PIPE_FEED_BYTES));
+    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
@@ -2157,7 +2220,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 (;;) {
@@ -2183,6 +2246,8 @@ virCommandProcessIO(virCommandPtr cmd)
             nfds++;
         }
 
+        nfds += virCommandSendBuffersFillPollfd(cmd, fds, nfds);
+
         if (nfds == 0)
             break;
 
@@ -2255,6 +2320,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