From patchwork Wed Feb 4 10:36:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fam Zheng X-Patchwork-Id: 5775791 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8577CBF440 for ; Wed, 4 Feb 2015 10:39:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AC399201FB for ; Wed, 4 Feb 2015 10:39:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AC50B202FE for ; Wed, 4 Feb 2015 10:39:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965576AbbBDKjL (ORCPT ); Wed, 4 Feb 2015 05:39:11 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38766 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965460AbbBDKjH (ORCPT ); Wed, 4 Feb 2015 05:39:07 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t14AcHLn006999 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 4 Feb 2015 05:38:17 -0500 Received: from ad.nay.redhat.com (dhcp-14-137.nay.redhat.com [10.66.14.137]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t14AawuS002023; Wed, 4 Feb 2015 05:38:02 -0500 From: Fam Zheng To: linux-kernel@vger.kernel.org Cc: Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , x86@kernel.org, Alexander Viro , Andrew Morton , Kees Cook , Andy Lutomirski , David Herrmann , Alexei Starovoitov , Miklos Szeredi , David Drysdale , Oleg Nesterov , "David S. Miller" , Vivek Goyal , Mike Frysinger , "Theodore Ts'o" , Heiko Carstens , Rasmus Villemoes , Rashika Kheria , Hugh Dickins , Mathieu Desnoyers , Fam Zheng , Peter Zijlstra , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, Josh Triplett , "Michael Kerrisk (man-pages)" , Paolo Bonzini , Omar Sandoval Subject: [PATCH RFC v2 4/7] epoll: Add implementation for epoll_ctl_batch Date: Wed, 4 Feb 2015 18:36:50 +0800 Message-Id: <1423046213-7043-5-git-send-email-famz@redhat.com> In-Reply-To: <1423046213-7043-1-git-send-email-famz@redhat.com> References: <1423046213-7043-1-git-send-email-famz@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This new syscall is a batched version of epoll_ctl. It will execute each command as specified in cmds in given order, and stop at first failure or upon completion of all commands. Signed-off-by: Fam Zheng --- fs/eventpoll.c | 48 ++++++++++++++++++++++++++++++++++++++++++ include/linux/syscalls.h | 4 ++++ include/uapi/linux/eventpoll.h | 11 ++++++++++ 3 files changed, 63 insertions(+) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index a1c313c..4eb40e0 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -2067,6 +2067,54 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events, sigmask ? &ksigmask : NULL); } +SYSCALL_DEFINE4(epoll_ctl_batch, int, epfd, int, flags, + int, ncmds, struct epoll_ctl_cmd __user *, cmds) +{ + struct epoll_ctl_cmd *kcmds = NULL; + int i, r, ret = 0; + int cmd_size; + + if (flags) + return -EINVAL; + if (ncmds <= 0 || !cmds) + return -EINVAL; + cmd_size = sizeof(struct epoll_ctl_cmd) * ncmds; + kcmds = kmalloc(cmd_size, GFP_KERNEL); + if (!kcmds) + return -ENOMEM; + if (copy_from_user(kcmds, cmds, cmd_size)) { + ret = -EFAULT; + goto out; + } + for (i = 0; i < ncmds; i++) { + struct epoll_event ev = (struct epoll_event) { + .events = kcmds[i].events, + .data = kcmds[i].data, + }; + if (kcmds[i].flags) { + kcmds[i].error_hint = -EINVAL; + goto copy; + } + kcmds[i].error_hint = ep_ctl_do(epfd, kcmds[i].op, + kcmds[i].fd, ev); + if (kcmds[i].error_hint) + goto copy; + ret++; + } +copy: + r = copy_to_user(cmds, kcmds, + sizeof(struct epoll_ctl_cmd) * ncmds); + /* Failing to copy the command results back will leave + * userspace no way to know the actual error code, but we still + * report the number of succeeded commands with ret, so it's + * not a big problem. Ignore it for now. + */ + (void) r; +out: + kfree(kcmds); + return ret; +} + #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events, diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 85893d7..117822c 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -12,6 +12,7 @@ #define _LINUX_SYSCALLS_H struct epoll_event; +struct epoll_ctl_cmd; struct iattr; struct inode; struct iocb; @@ -630,6 +631,9 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, int maxevents, int timeout, const sigset_t __user *sigmask, size_t sigsetsize); +asmlinkage long sys_epoll_ctl_batch(int epfd, int flags, + int ncmds, + struct epoll_ctl_cmd __user *cmds); asmlinkage long sys_gethostname(char __user *name, int len); asmlinkage long sys_sethostname(char __user *name, int len); asmlinkage long sys_setdomainname(char __user *name, int len); diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h index bc81fb2..bbdce3d 100644 --- a/include/uapi/linux/eventpoll.h +++ b/include/uapi/linux/eventpoll.h @@ -18,6 +18,8 @@ #include #include +#include + /* Flags for epoll_create1. */ #define EPOLL_CLOEXEC O_CLOEXEC @@ -61,6 +63,15 @@ struct epoll_event { __u64 data; } EPOLL_PACKED; +struct epoll_ctl_cmd { + int flags; + int op; + int fd; + __u32 events; + __u64 data; + int error_hint; +} EPOLL_PACKED; + #ifdef CONFIG_PM_SLEEP static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev) {