From patchwork Tue Mar 10 01:49:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fam Zheng X-Patchwork-Id: 5973631 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 584AF9F380 for ; Tue, 10 Mar 2015 01:54:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 719C020295 for ; Tue, 10 Mar 2015 01:54:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 647F720222 for ; Tue, 10 Mar 2015 01:54:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752369AbbCJBvd (ORCPT ); Mon, 9 Mar 2015 21:51:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60891 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751515AbbCJBv3 (ORCPT ); Mon, 9 Mar 2015 21:51:29 -0400 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 t2A1ob41022933 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 9 Mar 2015 21:50:37 -0400 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 t2A1nJN9004165; Mon, 9 Mar 2015 21:50:22 -0400 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 , Jonathan Corbet , shane.seymour@hp.com, dan.j.rosenberg@gmail.com Subject: [PATCH v4 4/9] epoll: Add implementation for epoll_ctl_batch Date: Tue, 10 Mar 2015 09:49:10 +0800 Message-Id: <1425952155-27603-5-git-send-email-famz@redhat.com> In-Reply-To: <1425952155-27603-1-git-send-email-famz@redhat.com> References: <1425952155-27603-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 | 50 ++++++++++++++++++++++++++++++++++++++++++ include/linux/syscalls.h | 4 ++++ include/uapi/linux/eventpoll.h | 11 ++++++++++ 3 files changed, 65 insertions(+) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 7909c88..54dc63f 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -99,6 +99,8 @@ #define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) +#define EP_MAX_BATCH (INT_MAX / sizeof(struct epoll_ctl_cmd)) + #define EP_UNACTIVE_PTR ((void *) -1L) #define EP_ITEM_COST (sizeof(struct epitem) + sizeof(struct eppoll_entry)) @@ -2069,6 +2071,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, ret = 0; + size_t cmd_size; + + if (flags) + return -EINVAL; + if (!cmds || ncmds <= 0 || ncmds > EP_MAX_BATCH) + return -EINVAL; + cmd_size = sizeof(struct epoll_ctl_cmd) * ncmds; + /* TODO: optimize for small arguments like select/poll with a stack + * allocated buffer */ + + 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].result = -EINVAL; + goto copy; + } + kcmds[i].result = ep_ctl_do(epfd, kcmds[i].op, + kcmds[i].fd, ev); + if (kcmds[i].result) + goto copy; + ret++; + } +copy: + /* We lose the number of succeeded commands in favor of returning + * -EFAULT, but in this case the application will want to fix the + * memory bug first. */ + if (copy_to_user(cmds, kcmds, cmd_size)) + ret = -EFAULT; +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 76d1e38..7d784e3 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; @@ -634,6 +635,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..4e18b17 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 result; +} EPOLL_PACKED; + #ifdef CONFIG_PM_SLEEP static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev) {