From patchwork Sun Mar 2 19:36:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 25579 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f70.google.com (mail-oa0-f70.google.com [209.85.219.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 7908D206F9 for ; Sun, 2 Mar 2014 19:36:48 +0000 (UTC) Received: by mail-oa0-f70.google.com with SMTP id n16sf24757951oag.9 for ; Sun, 02 Mar 2014 11:36:48 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=LWgZJrtyTmHWda+oyBdYfNqHQhMQTd+u+udnITzEWnw=; b=ikC5MCaV+XcZ0fnCzAjxZWPQZSxvYBzzSUkGD0W96OczMOYH0ZIXd3m+hf0prQqgrK u8q3fbXv309y5ND0rsQnqmwsN6i69nN6l8pb+lYtk3ltVJD2G+XIOkGoiS86vqwJZDGs 5B3oqcew3XwhKQ/PzE7WSbR/kuwuv4Vvu4kZl0U/Cz3Eeu75M6LW9ZQ2hMv084M6xPp3 iHa+LO8QV5ESE9Y55lcrVsuBfnXDN6W7VdX3ulVYx8y8iHWzM5I2lDpHkRxrRhuQdsV+ FSg55q8iUG4LRnprOKz8GOJ990bFWwMh2w01rKIK17g3BYUy32Ri0eJpfZn89F+QXauW dGQA== X-Gm-Message-State: ALoCoQnP7RVr4sSD3o+yYd57lBCioyuWFW6k250QTqhYqV6iz7mOSKt2ND/LjSaTKuVbKWow8/iw X-Received: by 10.42.115.129 with SMTP id k1mr9471131icq.25.1393789008023; Sun, 02 Mar 2014 11:36:48 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.82.148 with SMTP id h20ls1891328qgd.36.gmail; Sun, 02 Mar 2014 11:36:47 -0800 (PST) X-Received: by 10.52.27.9 with SMTP id p9mr22741035vdg.28.1393789007879; Sun, 02 Mar 2014 11:36:47 -0800 (PST) Received: from mail-ve0-f172.google.com (mail-ve0-f172.google.com [209.85.128.172]) by mx.google.com with ESMTPS id b20si2477031veu.68.2014.03.02.11.36.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 02 Mar 2014 11:36:47 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.172 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.172; Received: by mail-ve0-f172.google.com with SMTP id jx11so2836338veb.17 for ; Sun, 02 Mar 2014 11:36:47 -0800 (PST) X-Received: by 10.58.134.101 with SMTP id pj5mr12835veb.38.1393789007144; Sun, 02 Mar 2014 11:36:47 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.130.193 with SMTP id u1csp8759vcs; Sun, 2 Mar 2014 11:36:46 -0800 (PST) X-Received: by 10.112.14.1 with SMTP id l1mr2799984lbc.39.1393789005454; Sun, 02 Mar 2014 11:36:45 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id rl8si11410724lbb.59.2014.03.02.11.36.44 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sun, 02 Mar 2014 11:36:45 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1WKCBm-0007o1-O7; Sun, 02 Mar 2014 19:36:42 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Michael Matz , Andreas Schwab , Riku Voipio Subject: [PATCH 5/5] linux-user: Implement sendmmsg syscall Date: Sun, 2 Mar 2014 19:36:42 +0000 Message-Id: <1393789002-29960-6-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1393789002-29960-1-git-send-email-peter.maydell@linaro.org> References: <1393789002-29960-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.172 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Alexander Graf Glibc when built for newer kernels assumes that the sendmmsg syscall is available. Without it, dns resolution simply fails to work. Wrap the syscall with existing infrastructure so that we don't have a host dependency on sendmmsg. To avoid locking the same area of guest memory twice (which will break if DEBUG_REMAP is defined) we pull the lock/unlock part of do_sendrecvmsg() out into its own function so the actual implementation can be shared. Signed-off-by: Alexander Graf [PMM: add recvmmsg support; handle errors (which also implies support for non-blocking operations); cap the vector length as the kernel implementation does; don't lock guest memory twice; support MSG_WAITFORONE flag] Signed-off-by: Peter Maydell --- linux-user/syscall.c | 86 +++++++++++++++++++++++++++++++++++++++++------ linux-user/syscall_defs.h | 4 +++ 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ccdbc4e..1f64867 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1904,23 +1904,16 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr, return get_errno(connect(sockfd, addr, addrlen)); } -/* do_sendrecvmsg() Must return target values and target errnos. */ -static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, - int flags, int send) +/* do_sendrecvmsg_locked() Must return target values and target errnos. */ +static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, + int flags, int send) { abi_long ret, len; - struct target_msghdr *msgp; struct msghdr msg; int count; struct iovec *vec; abi_ulong target_vec; - /* FIXME */ - if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, - msgp, - target_msg, - send ? 1 : 0)) - return -TARGET_EFAULT; if (msgp->msg_name) { msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); @@ -1975,10 +1968,75 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, out: unlock_iovec(vec, target_vec, count, !send); out2: + return ret; +} + +static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, + int flags, int send) +{ + abi_long ret; + struct target_msghdr *msgp; + + if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, + msgp, + target_msg, + send ? 1 : 0)) { + return -TARGET_EFAULT; + } + ret = do_sendrecvmsg_locked(fd, msgp, flags, send); unlock_user_struct(msgp, target_msg, send ? 0 : 1); return ret; } +#ifdef TARGET_NR_sendmmsg +/* We don't rely on the C library to have sendmmsg/recvmmsg support, + * so it might not have this *mmsg-specific flag either. + */ +#ifndef MSG_WAITFORONE +#define MSG_WAITFORONE 0x10000 +#endif + +static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, + unsigned int vlen, unsigned int flags, + int send) +{ + struct target_mmsghdr *mmsgp; + abi_long ret = 0; + int i; + + if (vlen > UIO_MAXIOV) { + vlen = UIO_MAXIOV; + } + + mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1); + if (!mmsgp) { + return -TARGET_EFAULT; + } + + for (i = 0; i < vlen; i++) { + ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send); + if (is_error(ret)) { + break; + } + mmsgp[i].msg_len = tswap32(ret); + /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ + if (flags & MSG_WAITFORONE) { + flags |= MSG_DONTWAIT; + } + } + + unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i); + + /* Return number of datagrams sent if we sent any at all; + * otherwise return the error. + */ + if (i) { + return i; + } + return ret; +} +#endif + /* If we don't have a system accept4() then just call accept. * The callsites to do_accept4() will ensure that they don't * pass a non-zero flags argument in this config. @@ -6716,6 +6774,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_sendrecvmsg(arg1, arg2, arg3, 1); break; #endif +#ifdef TARGET_NR_sendmmsg + case TARGET_NR_sendmmsg: + ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); + break; + case TARGET_NR_recvmmsg: + ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); + break; +#endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index d55f396..732c9e3 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -240,6 +240,10 @@ __target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cms return __cmsg; } +struct target_mmsghdr { + struct target_msghdr msg_hdr; /* Message header */ + unsigned int msg_len; /* Number of bytes transmitted */ +}; struct target_rusage { struct target_timeval ru_utime; /* user time used */