qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 08/17] add unix_msgfd_lookup() to callback get_buffe


From: Lei Li
Subject: [Qemu-devel] [PATCH 08/17] add unix_msgfd_lookup() to callback get_buffer
Date: Thu, 21 Nov 2013 17:11:31 +0800

The control message for exchange of pipe file descriptor should
be received by recvmsg, and it might be eaten to stream file by
qemu_recv() when receiving by two callbacks. So this patch adds
unix_msgfd_lookup() to callback get_buffer as the only one receiver,
where the pipe file descriptor would be caughted.

Signed-off-by: Lei Li <address@hidden>
---
 migration-local.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/migration-local.c b/migration-local.c
index e028beb..0f0896b 100644
--- a/migration-local.c
+++ b/migration-local.c
@@ -50,6 +50,8 @@ typedef struct QEMUFileLocal {
     bool unix_page_flipping;
 } QEMUFileLocal;
 
+static bool pipefd_passed;
+
 static int qemu_local_get_sockfd(void *opaque)
 {
     QEMUFileLocal *s = opaque;
@@ -57,16 +59,76 @@ static int qemu_local_get_sockfd(void *opaque)
     return s->sockfd;
 }
 
+static int unix_msgfd_lookup(void *opaque, struct msghdr *msg)
+{
+    QEMUFileLocal *s = opaque;
+    struct cmsghdr *cmsg;
+    bool found = false;
+
+    for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+        if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+            cmsg->cmsg_level != SOL_SOCKET ||
+            cmsg->cmsg_type != SCM_RIGHTS)
+            continue;
+
+        /* PIPE file descriptor to be received */
+        s->pipefd[0] = *((int *)CMSG_DATA(cmsg));
+    }
+
+    if (s->pipefd[0] <= 0) {
+        fprintf(stderr, "no pipe fd can be received\n");
+        return found;
+    }
+
+    DPRINTF("pipefd successfully received\n");
+    return s->pipefd[0];
+}
+
 static int qemu_local_get_buffer(void *opaque, uint8_t *buf,
                                  int64_t pos, int size)
 {
     QEMUFileLocal *s = opaque;
     ssize_t len;
+    struct msghdr msg = { NULL, };
+    struct iovec iov[1];
+    union {
+        struct cmsghdr cmsg;
+        char control[CMSG_SPACE(sizeof(int))];
+    } msg_control;
+
+    iov[0].iov_base = buf;
+    iov[0].iov_len = size;
+
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &msg_control;
+    msg.msg_controllen = sizeof(msg_control);
 
     for (;;) {
-        len = qemu_recv(s->sockfd, buf, size, 0);
-        if (len != -1) {
-            break;
+        if (!pipefd_passed) {
+            /*
+             * recvmsg is called here to catch the control message for
+             * the exchange of PIPE file descriptor until it is received.
+             */
+            len = recvmsg(s->sockfd, &msg, 0);
+            if (len != -1) {
+                if (unix_msgfd_lookup(s, &msg) > 0) {
+                    pipefd_passed = 1;
+                    /*
+                     * Do not count one byte taken by the PIPE file
+                     * descriptor.
+                     */
+                    len--;
+                } else {
+                    len = -1;
+                }
+                break;
+            }
+        } else {
+            len = qemu_recv(s->sockfd, buf, size, 0);
+            if (len != -1) {
+                break;
+            }
         }
 
         if (socket_error() == EAGAIN) {
-- 
1.7.7.6




reply via email to

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