From patchwork Tue May 27 12:04:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Nikolaev X-Patchwork-Id: 352888 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 471D1140098 for ; Tue, 27 May 2014 22:06:32 +1000 (EST) Received: from localhost ([::1]:33829 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WpG9G-0007GC-1b for incoming@patchwork.ozlabs.org; Tue, 27 May 2014 08:06:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43218) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WpG7M-0003wG-Q4 for qemu-devel@nongnu.org; Tue, 27 May 2014 08:04:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WpG7F-0007Ae-QG for qemu-devel@nongnu.org; Tue, 27 May 2014 08:04:32 -0400 Received: from mail-wi0-f179.google.com ([209.85.212.179]:60997) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WpG7F-0007AU-8F for qemu-devel@nongnu.org; Tue, 27 May 2014 08:04:25 -0400 Received: by mail-wi0-f179.google.com with SMTP id bs8so1535077wib.6 for ; Tue, 27 May 2014 05:04:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-type :content-transfer-encoding; bh=bB/B+WSU415G9gI3DUa3POgffrzyIQrLOVnmV8SdeHk=; b=VMl4DTeTs+lAtrvdi9VyNr/p7In2zn9NXNfuCHSFFJqNLsE/0m3IfptmEfQdgCqGIC S9c+w1bA+ISBJgHCiNaswet89oqCVOVmPq5ZO0QR7340kyrJuY6CTY1cI1vEDcZBD4ds CRdNU1e8phGOUm0koII8OegeTt8GiQ+eIEDCA0cXTRWq3CjK1M3pg8aindvyzraUM3x6 +y27ZSu5geXqMkbfYLDyRhUaQhZilMkiKt/WoZCDn8Gc6hechNz7mOt1r/exVkQdAyea r5Ol4Cqe4yz3HMdrPR17ROPw8Ulr7OevVlSPmSEPu8mZejtH+A8pRpBeOvUz0GYwgQmK U3VQ== X-Gm-Message-State: ALoCoQlwiNeev7Jj6lgMKDhvsK9MpvUHdfZkgKXfuubMFBUhCt8RqT9Iyuy6KZ/Xov26f8ViZZPS X-Received: by 10.180.75.7 with SMTP id y7mr21128335wiv.4.1401192262741; Tue, 27 May 2014 05:04:22 -0700 (PDT) Received: from [0.0.14.236] ([82.146.27.14]) by mx.google.com with ESMTPSA id fh5sm2876800wic.9.2014.05.27.05.04.21 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 27 May 2014 05:04:22 -0700 (PDT) From: Nikolay Nikolaev To: snabb-devel@googlegroups.com, qemu-devel@nongnu.org Date: Tue, 27 May 2014 15:04:15 +0300 Message-ID: <20140527120410.15172.24903.stgit@3820> In-Reply-To: <20140527120050.15172.94908.stgit@3820> References: <20140527120050.15172.94908.stgit@3820> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.212.179 Cc: a.motakis@virtualopensystems.com, luke@snabb.co, tech@virtualopensystems.com, n.nikolaev@virtualopensystems.com, mst@redhat.com Subject: [Qemu-devel] [PATCH v10 04/18] Add chardev API qemu_chr_fe_get_msgfds X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This extends the existing qemu_chr_fe_get_msgfd by allowing to read a set of fds. The function for receiving the fds - unix_process_msgfd is extended to allocate the needed array size. Signed-off-by: Antonios Motakis Signed-off-by: Nikolay Nikolaev --- include/sysemu/char.h | 15 ++++++++- qemu-char.c | 85 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/include/sysemu/char.h b/include/sysemu/char.h index d99dcf6..82eaaf5 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -61,7 +61,7 @@ struct CharDriverState { GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); - int (*get_msgfd)(struct CharDriverState *s); + int (*get_msgfds)(struct CharDriverState *s, int* fds, int num); int (*set_msgfds)(struct CharDriverState *s, int *fds, int num); int (*chr_add_client)(struct CharDriverState *chr, int fd); IOEventHandler *chr_event; @@ -230,6 +230,19 @@ int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg); int qemu_chr_fe_get_msgfd(CharDriverState *s); /** + * @qemu_chr_fe_get_msgfds: + * + * For backends capable of fd passing, return the number of file received + * descriptors and fills the fds array up to num elements + * + * Returns: -1 if fd passing isn't supported or there are no pending file + * descriptors. If file descriptors are returned, subsequent calls to + * this function will return -1 until a client sends a new set of file + * descriptors. + */ +int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int num); + +/** * @qemu_chr_fe_set_msgfds: * * For backends capable of fd passing, set an array of fds to be passed with diff --git a/qemu-char.c b/qemu-char.c index 53fae51..e5c1cf9 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -204,7 +204,13 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len) int qemu_chr_fe_get_msgfd(CharDriverState *s) { - return s->get_msgfd ? s->get_msgfd(s) : -1; + int fd; + return (qemu_chr_fe_get_msgfds(s, &fd, 1) >= 0) ? fd : -1; +} + +int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int len) +{ + return s->get_msgfds ? s->get_msgfds(s, fds, len) : -1; } int qemu_chr_fe_set_msgfds(CharDriverState *s, int *fds, int num) @@ -2337,7 +2343,8 @@ typedef struct { int do_telnetopt; int do_nodelay; int is_unix; - int msgfd; + int *read_msgfds; + int read_msgfds_num; int *write_msgfds; int write_msgfds_num; } TCPCharDriver; @@ -2469,12 +2476,20 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } -static int tcp_get_msgfd(CharDriverState *chr) +static int tcp_get_msgfds(CharDriverState *chr, int *fds, int num) { TCPCharDriver *s = chr->opaque; - int fd = s->msgfd; - s->msgfd = -1; - return fd; + int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num; + + if (to_copy) { + memcpy(fds, s->read_msgfds, to_copy * sizeof(int)); + + g_free(s->read_msgfds); + s->read_msgfds = 0; + s->read_msgfds_num = 0; + } + + return to_copy; } static int tcp_set_msgfds(CharDriverState *chr, int *fds, int num) @@ -2503,26 +2518,46 @@ static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { - int fd; + int fd_size, i; - if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) || cmsg->cmsg_level != SOL_SOCKET || - cmsg->cmsg_type != SCM_RIGHTS) + cmsg->cmsg_type != SCM_RIGHTS) { continue; + } + + fd_size = cmsg->cmsg_len - CMSG_LEN(0); - fd = *((int *)CMSG_DATA(cmsg)); - if (fd < 0) + if (!fd_size) { continue; + } - /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ - qemu_set_block(fd); + /* close and clean read_msgfds */ + for (i = 0; i < s->read_msgfds_num; i++) { + close(s->read_msgfds[i]); + } -#ifndef MSG_CMSG_CLOEXEC - qemu_set_cloexec(fd); -#endif - if (s->msgfd != -1) - close(s->msgfd); - s->msgfd = fd; + if (s->read_msgfds_num) { + g_free(s->read_msgfds); + } + + s->read_msgfds_num = fd_size / sizeof(int); + s->read_msgfds = g_malloc(fd_size); + memcpy(s->read_msgfds, CMSG_DATA(cmsg), fd_size); + + for (i = 0; i < s->read_msgfds_num; i++) { + int fd = s->read_msgfds[i]; + if (fd < 0) { + continue; + } + + /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ + qemu_set_block(fd); + + #ifndef MSG_CMSG_CLOEXEC + qemu_set_cloexec(fd); + #endif + } } } @@ -2740,6 +2775,7 @@ static gboolean tcp_chr_accept(GIOChannel *channel, GIOCondition cond, void *opa static void tcp_chr_close(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; + int i; if (s->fd >= 0) { remove_fd_in_watch(chr); if (s->chan) { @@ -2757,6 +2793,12 @@ static void tcp_chr_close(CharDriverState *chr) } closesocket(s->listen_fd); } + if (s->read_msgfds_num) { + for (i = 0; i < s->read_msgfds_num; i++) { + close(s->read_msgfds[i]); + } + g_free(s->read_msgfds); + } if (s->write_msgfds_num) { g_free(s->write_msgfds); } @@ -2788,7 +2830,8 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay, s->connected = 0; s->fd = -1; s->listen_fd = -1; - s->msgfd = -1; + s->read_msgfds = 0; + s->read_msgfds_num = 0; s->write_msgfds = 0; s->write_msgfds_num = 0; @@ -2821,7 +2864,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay, chr->chr_write = tcp_chr_write; chr->chr_sync_read = tcp_chr_sync_read; chr->chr_close = tcp_chr_close; - chr->get_msgfd = tcp_get_msgfd; + chr->get_msgfds = tcp_get_msgfds; chr->set_msgfds = tcp_set_msgfds; chr->chr_add_client = tcp_chr_add_client; chr->chr_add_watch = tcp_chr_add_watch;