diff mbox

[RFC,1/2] Allow recvmsg for qemu char devices

Message ID 1248971307-8421-1-git-send-email-cam@cs.ualberta.ca (mailing list archive)
State New, archived
Headers show

Commit Message

Cam Macdonell July 30, 2009, 4:28 p.m. UTC
This patch allows switching from the standard recv to recvmsg for a qemu char
device.  Switching allows file descriptors to be passed with SCM_RIGHTS to a
qemu process.  Instead of receiving a buffer of data the recvmsg call back is
passed a 'struct msghdr'.

The patch also adds a function to add an eventfd as qemu char device.  Perhaps
this should be a separate patch.

This is not an elegant solution to supporting recvmsg so suggestions are
especially welcome.

---
 qemu-char.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-char.h |    8 ++++++
 2 files changed, 80 insertions(+), 0 deletions(-)

Comments

Anthony Liguori July 30, 2009, 6:28 p.m. UTC | #1
Cam Macdonell wrote:
> This patch allows switching from the standard recv to recvmsg for a qemu char
> device.  Switching allows file descriptors to be passed with SCM_RIGHTS to a
> qemu process.  Instead of receiving a buffer of data the recvmsg call back is
> passed a 'struct msghdr'.
>
> The patch also adds a function to add an eventfd as qemu char device.  Perhaps
> this should be a separate patch.
>
> This is not an elegant solution to supporting recvmsg so suggestions are
> especially welcome.
>   

Use the sendfd/closefd commands that Mark introduced.

Regards,

Anthony Liguori
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/qemu-char.c b/qemu-char.c
index 287e0cd..c1620c2 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -168,6 +168,11 @@  void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
     s->chr_read(s->handler_opaque, buf, len);
 }
 
+void qemu_chr_recvmsg(CharDriverState *s, struct msghdr *msg, int flags)
+{
+    s->chr_read(s->handler_opaque, msg, flags);
+}
+
 void qemu_chr_accept_input(CharDriverState *s)
 {
     if (s->chr_accept_input)
@@ -1652,6 +1657,7 @@  static CharDriverState *qemu_chr_open_win_pipe(const char *filename)
     WinCharState *s;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
+
     s = qemu_mallocz(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1937,6 +1943,72 @@  static void tcp_chr_read(void *opaque)
     }
 }
 
+/* this is a new function that will replace tcp_chr_read (which calls recv)
+ * with this one that calls recvmsg instead when we want to use recvmsg */
+static void tcp_chr_recvmsg(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    TCPCharDriver *s = chr->opaque;
+    struct msghdr msg;
+    uint8_t buf[1024];
+    int len, size;
+    char control[CMSG_SPACE(RECVMSG_MAX)];
+    struct iovec iov[8];
+
+    printf("inside tcp_chr_recvmsg\n");
+    msg.msg_name = 0;
+    msg.msg_namelen = 0;
+    msg.msg_control = control;
+    msg.msg_controllen = sizeof(control);
+    msg.msg_flags = 0;
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+
+    iov[0].iov_base = buf;
+    iov[0].iov_len = 1024;
+
+    if (!s->connected || s->max_size <= 0)
+        return;
+    len = sizeof(control);
+    if (len > s->max_size)
+        len = s->max_size;
+//    size = recv(s->fd, buf, len, 0);
+    printf("calling recvmsg\n");
+    size = recvmsg(s->fd, &msg, 0);
+    if (size == 0) {
+        /* connection closed */
+        s->connected = 0;
+        if (s->listen_fd >= 0) {
+            qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+        }
+        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        closesocket(s->fd);
+        s->fd = -1;
+    } else if (size > 0) {
+        if (s->do_telnetopt)
+            tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+        if (size > 0)
+            qemu_chr_recvmsg(chr, &msg, 0);
+    }
+
+
+}
+
+void tcp_switch_to_recvmsg_handlers(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    TCPCharDriver *s = chr->opaque;
+
+    qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
+                         tcp_chr_recvmsg, NULL, chr);
+}
+
+CharDriverState *qemu_chr_open_eventfd(int eventfd){
+
+    return qemu_chr_open_fd(eventfd, eventfd);
+
+}
+
 static void tcp_chr_connect(void *opaque)
 {
     CharDriverState *chr = opaque;
diff --git a/qemu-char.h b/qemu-char.h
index e1aa8db..5fe6c43 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -44,6 +44,8 @@  typedef struct {
 #define CHR_TIOCM_DTR	0x002
 #define CHR_TIOCM_RTS	0x004
 
+#define RECVMSG_MAX    1024
+
 typedef void IOEventHandler(void *opaque, int event);
 
 struct CharDriverState {
@@ -84,6 +86,12 @@  void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
 void qemu_chr_accept_input(CharDriverState *s);
 void qemu_chr_info(Monitor *mon);
 
+/* function to change tcp_chr_read to tcp_chr_recvmsg */
+void tcp_switch_to_recvmsg_handlers(void *opaque);
+
+/* add an eventfd to the qemu devices that are polled */
+CharDriverState *qemu_chr_open_eventfd(int eventfd);
+
 extern int term_escape_char;
 
 /* async I/O support */