From patchwork Thu Jul 30 16:28:27 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cam Macdonell X-Patchwork-Id: 38346 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6UGSpjN013311 for ; Thu, 30 Jul 2009 16:28:52 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751155AbZG3Q2s (ORCPT ); Thu, 30 Jul 2009 12:28:48 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751096AbZG3Q2s (ORCPT ); Thu, 30 Jul 2009 12:28:48 -0400 Received: from fleet.cs.ualberta.ca ([129.128.22.22]:55130 "EHLO fleet.cs.ualberta.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751095AbZG3Q2s (ORCPT ); Thu, 30 Jul 2009 12:28:48 -0400 Received: from localhost.localdomain (st-brides.cs.ualberta.ca [129.128.23.21]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp-auth.cs.ualberta.ca (Postfix) with ESMTP id 6D40E28074; Thu, 30 Jul 2009 10:28:48 -0600 (MDT) From: Cam Macdonell To: kvm@vger.kernel.org Cc: qemu-devel@nongnu.org, Cam Macdonell Subject: [PATCH RFC 1/2] Allow recvmsg for qemu char devices Date: Thu, 30 Jul 2009 10:28:27 -0600 Message-Id: <1248971307-8421-1-git-send-email-cam@cs.ualberta.ca> X-Mailer: git-send-email 1.6.0.6 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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(-) 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 */