[libvirt] [PATCH v5 14/20] utils: Extend virCommandProcessIO to include the send buffers

Stefan Berger stefanb at linux.vnet.ibm.com
Fri Jul 12 16:23:48 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 | 62 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index bb9ecdf348..976231444e 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -1815,6 +1815,61 @@ virCommandSetSendBuffer(virCommandPtr cmd,
 }
 
 
+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;
+    int 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
@@ -2169,7 +2224,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 (;;) {
@@ -2195,6 +2250,8 @@ virCommandProcessIO(virCommandPtr cmd)
             nfds++;
         }
 
+        nfds += virCommandSendBuffersFillPollfd(cmd, fds, nfds);
+
         if (nfds == 0)
             break;
 
@@ -2267,6 +2324,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