From patchwork Sat Oct 28 12:58:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Tao X-Patchwork-Id: 10030979 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 951E16032C for ; Sat, 28 Oct 2017 12:53:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 878882883B for ; Sat, 28 Oct 2017 12:53:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7BE7C28ADF; Sat, 28 Oct 2017 12:53:57 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 31F972883B for ; Sat, 28 Oct 2017 12:53:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751447AbdJ1Mwl (ORCPT ); Sat, 28 Oct 2017 08:52:41 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:9469 "EHLO szxga04-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751269AbdJ1Mwb (ORCPT ); Sat, 28 Oct 2017 08:52:31 -0400 Received: from 172.30.72.59 (EHLO DGGEMS408-HUB.china.huawei.com) ([172.30.72.59]) by dggrg04-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id DJY13235; Sat, 28 Oct 2017 20:52:21 +0800 (CST) Received: from huawei.com (10.175.124.28) by DGGEMS408-HUB.china.huawei.com (10.3.19.208) with Microsoft SMTP Server id 14.3.361.1; Sat, 28 Oct 2017 20:52:15 +0800 From: Hou Tao To: CC: , , , , , Subject: [RFC][PATCH 6/8] epoll: ensure the validity of ep when removing epi in eventpoll_release_file() Date: Sat, 28 Oct 2017 20:58:25 +0800 Message-ID: <1509195507-29037-7-git-send-email-houtao1@huawei.com> X-Mailer: git-send-email 2.7.5 In-Reply-To: <1509195507-29037-1-git-send-email-houtao1@huawei.com> References: <1509195507-29037-1-git-send-email-houtao1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.124.28] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090204.59F47D85.0025, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: fd88fe4bbbe48c281cf495deef6d48e3 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 Before the removal of epmutex, ep_free() will be blocked by epmutex when invoking eventpoll_release_file(), so epi->ep will be valid. After the removal of epmutex, epi->ep may be freed during the invocation of eventpoll_release_file(). We can not use rcu_read_lock/unlock because we needs to acquire ep->mtx which is a mutex, so we add a ref-counter to eventpoll and increase it before leaving the rcu read critical region. Signed-off-by: Hou Tao --- fs/eventpoll.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index e1e4796..27b743b 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -43,6 +43,7 @@ #include #include #include +#include /* * LOCKING: @@ -231,6 +232,8 @@ struct eventpoll { unsigned int napi_id; #endif + /* used to ensure the validity of eventpoll when release file */ + refcount_t ref; /* used to free itself */ struct rcu_head rcu; }; @@ -827,6 +830,25 @@ static void ep_rcu_free(struct rcu_head *head) kfree(ep); } +static void eventpoll_put_ep(struct eventpoll *ep) +{ + if (refcount_dec_and_test(&ep->ref)) { + mutex_destroy(&ep->mtx); + free_uid(ep->user); + wakeup_source_unregister(ep->ws); + + call_rcu(&ep->rcu, ep_rcu_free); + } +} + +static struct eventpoll *eventpoll_get_ep(struct eventpoll *ep) +{ + if (refcount_inc_not_zero(&ep->ref)) + return ep; + else + return NULL; +} + static void ep_free(struct eventpoll *ep) { struct rb_node *rbp; @@ -883,11 +905,7 @@ static void ep_free(struct eventpoll *ep) mutex_unlock(&epmutex); } - mutex_destroy(&ep->mtx); - free_uid(ep->user); - wakeup_source_unregister(ep->ws); - - call_rcu(&ep->rcu, ep_rcu_free); + eventpoll_put_ep(ep); } static int ep_eventpoll_release(struct inode *inode, struct file *file) @@ -1018,7 +1036,7 @@ static const struct file_operations eventpoll_fops = { void eventpoll_release_file(struct file *file) { struct eventpoll *ep; - struct epitem *epi, *next; + struct epitem *epi; /* * We don't want to get "file->f_lock" because it is not @@ -1039,13 +1057,18 @@ void eventpoll_release_file(struct file *file) if (!epi) break; - ep = epi->ep; + ep = eventpoll_get_ep(epi->ep); + /* Current epi has been removed by ep_free() */ + if (!ep) + continue; rcu_read_unlock(); mutex_lock_nested(&ep->mtx, 0); ep_remove(ep, epi); mutex_unlock(&ep->mtx); + eventpoll_put_ep(ep); + rcu_read_lock(); } rcu_read_unlock(); @@ -1084,6 +1107,7 @@ static int ep_alloc(struct eventpoll **pep) ep->ovflist = EP_UNACTIVE_PTR; ep->user = user; INIT_LIST_HEAD(&ep->visited_list_link); + refcount_set(&ep->ref, 1); *pep = ep;