From patchwork Wed Feb 15 16:14:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyrill Gorcunov X-Patchwork-Id: 9574385 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2E6B760493 for ; Wed, 15 Feb 2017 16:15:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1DC312846B for ; Wed, 15 Feb 2017 16:15:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1225E284D9; Wed, 15 Feb 2017 16:15:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8B10228489 for ; Wed, 15 Feb 2017 16:15:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751614AbdBOQPG (ORCPT ); Wed, 15 Feb 2017 11:15:06 -0500 Received: from mail-lf0-f66.google.com ([209.85.215.66]:33489 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752075AbdBOQPD (ORCPT ); Wed, 15 Feb 2017 11:15:03 -0500 Received: by mail-lf0-f66.google.com with SMTP id x1so13858806lff.0; Wed, 15 Feb 2017 08:14:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=YN7XFw2hD9JeLI0+0iQS3isbLEaYmUbOqeEVSm1Q4TA=; b=JKAon92g3nrkZ7fMi9UAfPE48z6hFljevO4lVcn0xt7rdvAQ40ZO1ujEiYmdgBv94l 3fyxaMgu+KcnI8TgW4DWikD6iyxM4/Iwo1CuKQCG+FBQUotSJEX/qbGgyiCbgTwRBtli 7+VHonNkva5atRQfw6Ya7o+IeTEKaq9J8IJ9oUDHdTQKZYw8wG2JMrtW3TSho3Lb6IdU aE8BsKp6oiiM8ZFQT+3gDX9jwxeagrher+mWWebohke8/gArGOwdeE/cmD4zsJ6xvn3k E70qYvgZmALNT8xA7l2SAgRqVy+L+KpcrWOveBMaJJtd9ILR7paU/hOrTiwErUz1TWpv xKYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=YN7XFw2hD9JeLI0+0iQS3isbLEaYmUbOqeEVSm1Q4TA=; b=PL6YRsiQ+7skJHY5Z1Ic7S/sNb9wjXbPuC+bAl18OL+Bc3/T8S8LS1fowvzeV1HTfw dyuQVZMeTJEAzuS0iiNnenAew922FIVh2Dmvhoq2gmfAjm3/tJUkWWvSuGPx0kd2sbZL eyN6Ega7D1E1ZLMGRIQ4NO4HJiGXYXhNcXZ306jW7s1LjRDPLLvqkl6wacbl3/2cDA2t iwOfC8xDft9oPVZgM/qRFQrHDvoXN/tIa9NgdYbIhKri2NAqnlIKpFSXKklQg4REmvmW 2O+uRGqq6fKXwu8ug09e2HCRbYgetK9rw2e5WlDG7cvaE3cTzqmuxJpuWf6fWr1JmZ3i IH2g== X-Gm-Message-State: AMke39mNIj69ynXYKLrdPANRYKI4Hm4bOLtrVILoWK74Ic2Ucsu4ZjHsBT4isArwtZLdPA== X-Received: by 10.25.21.96 with SMTP id l93mr12023790lfi.136.1487175296396; Wed, 15 Feb 2017 08:14:56 -0800 (PST) Received: from uranus.localdomain ([5.18.234.157]) by smtp.gmail.com with ESMTPSA id w17sm1035049ljd.54.2017.02.15.08.14.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Feb 2017 08:14:55 -0800 (PST) Received: by uranus.localdomain (Postfix, from userid 1000) id 0B0482183B; Wed, 15 Feb 2017 19:14:54 +0300 (MSK) Date: Wed, 15 Feb 2017 19:14:54 +0300 From: Cyrill Gorcunov To: LINUXFS-ML , LKML Cc: Al Viro , Andrew Morton , Andrey Vagin , Pavel Emelyanov Subject: [RFC] fs, eventpoll: Add ability to install target file by its number Message-ID: <20170215161453.GA13021@uranus> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.7.1 (2016-10-04) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When we checkpoint a process we look into /proc//fdinfo/ of eventpoll file and parse target files list from there. In most situations this is fine because target file is present in the /proc//fd/ list. But in case if file descriptor was dup'ed or transferred via unix socket and closed after, it might not be in the list and we can't figure out which file descriptor to pass into epoll_ctl call. To resolve this tie lets add EPOLL_CTL_ITF ("itf" stands for install target file) operation which simply takes target file descriptor number and installs it into a caller's file table, thus we can use kcmp() syscall and figure out which exactly file to be added into eventpoll on restore procedure. Signed-off-by: Cyrill Gorcunov CC: Andrey Vagin CC: Pavel Emelyanov CC: Al Viro CC: Andrew Morton --- fs/eventpoll.c | 74 +++++++++++++++++++++++++++++++++++------ include/uapi/linux/eventpoll.h | 1 2 files changed, 65 insertions(+), 10 deletions(-) Index: linux-ml.git/fs/eventpoll.c =================================================================== --- linux-ml.git.orig/fs/eventpoll.c +++ linux-ml.git/fs/eventpoll.c @@ -361,7 +361,7 @@ static inline struct epitem *ep_item_fro /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */ static inline int ep_op_has_event(int op) { - return op != EPOLL_CTL_DEL; + return op != EPOLL_CTL_DEL && op != EPOLL_CTL_ITF; } /* Initialize the poll safe wake up structure */ @@ -967,6 +967,20 @@ free_uid: return error; } +static struct epitem *ep_find_tfd(struct eventpoll *ep, int tfd) +{ + struct rb_node *rbp; + struct epitem *epi; + + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (epi->ffd.fd == tfd) + return epi; + } + + return NULL; +} + /* * Search the file inside the eventpoll tree. The RB tree operations * are protected by the "mtx" mutex, and ep_find() must be called with @@ -979,6 +993,9 @@ static struct epitem *ep_find(struct eve struct epitem *epi, *epir = NULL; struct epoll_filefd ffd; + if (unlikely(!file)) + return ep_find_tfd(ep, fd); + ep_set_ffd(&ffd, file, fd); for (rbp = ep->rbr.rb_node; rbp; ) { epi = rb_entry(rbp, struct epitem, rbn); @@ -1787,6 +1804,28 @@ static void clear_tfile_check_list(void) INIT_LIST_HEAD(&tfile_check_list); } +static int ep_install_tfd(struct eventpoll *ep, struct epitem *epi) +{ + struct file *file; + int ret = -ENOENT; + + rcu_read_lock(); + if (get_file_rcu(epi->ffd.file)) + file = epi->ffd.file; + else + file = NULL; + rcu_read_unlock(); + + if (file) { + ret = get_unused_fd_flags(0); + if (ret >= 0) + fd_install(ret, file); + else + fput(file); + } + return ret; +} + /* * Open an eventpoll file descriptor. */ @@ -1867,15 +1906,24 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in if (!f.file) goto error_return; - /* Get the "struct file *" for the target file */ - tf = fdget(fd); - if (!tf.file) - goto error_fput; - - /* The target file descriptor must support poll */ - error = -EPERM; - if (!tf.file->f_op->poll) - goto error_tgt_fput; + if (likely(op != EPOLL_CTL_ITF)) { + /* Get the "struct file *" for the target file */ + tf = fdget(fd); + if (!tf.file) + goto error_fput; + + /* The target file descriptor must support poll */ + error = -EPERM; + if (!tf.file->f_op->poll) + goto error_tgt_fput; + } else { + /* + * A special case where target file + * is to be looked up and installed + * into a caller. + */ + memset(&tf, 0, sizeof(tf)); + } /* Check if EPOLLWAKEUP is allowed */ if (ep_op_has_event(op)) @@ -1972,6 +2020,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in else error = -ENOENT; break; + case EPOLL_CTL_ITF: + if (epi) + error = ep_install_tfd(ep, epi); + else + error = -ENOENT; + break; case EPOLL_CTL_MOD: if (epi) { if (!(epi->event.events & EPOLLEXCLUSIVE)) { Index: linux-ml.git/include/uapi/linux/eventpoll.h =================================================================== --- linux-ml.git.orig/include/uapi/linux/eventpoll.h +++ linux-ml.git/include/uapi/linux/eventpoll.h @@ -25,6 +25,7 @@ #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_DEL 2 #define EPOLL_CTL_MOD 3 +#define EPOLL_CTL_ITF 4 /* Set exclusive wakeup mode for the target file descriptor */ #define EPOLLEXCLUSIVE (1 << 28)