From patchwork Thu Apr 13 13:49:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Tao X-Patchwork-Id: 9679443 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 AFCE560383 for ; Thu, 13 Apr 2017 13:49:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0EDB28609 for ; Thu, 13 Apr 2017 13:49:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 940AB28652; Thu, 13 Apr 2017 13:49:35 +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=ham 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 0EC8E28609 for ; Thu, 13 Apr 2017 13:49:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753273AbdDMNtb (ORCPT ); Thu, 13 Apr 2017 09:49:31 -0400 Received: from szxga03-in.huawei.com ([45.249.212.189]:5437 "EHLO dggrg03-dlp.huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752465AbdDMNta (ORCPT ); Thu, 13 Apr 2017 09:49:30 -0400 Received: from 172.30.72.54 (EHLO DGGEML402-HUB.china.huawei.com) ([172.30.72.54]) by dggrg03-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id ALQ65804; Thu, 13 Apr 2017 21:48:15 +0800 (CST) Received: from huawei.com (10.175.124.28) by DGGEML402-HUB.china.huawei.com (10.3.17.38) with Microsoft SMTP Server id 14.3.301.0; Thu, 13 Apr 2017 21:48:11 +0800 From: Hou Tao To: , CC: , Subject: [RFC][PATCH] proc: invalidate the deleting or deleted proc dentry Date: Thu, 13 Apr 2017 21:49:35 +0800 Message-ID: <1492091375-18642-1-git-send-email-houtao1@huawei.com> X-Mailer: git-send-email 2.5.0 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.0A020205.58EF81A0.016F, 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: 656fee2fbd96b8f76cff7c3270520cba 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 After the invocation of remove_proc_entry() for a proc fs directory, if the related dentry had been held by some processes (eg., by chdir), the lookup afterwards will still return the old proc_dir_entry. The new created proc fs files under the proc fs directory will not be visible until the old dentry is released, and this makes our hotplug process to fail which needs to access the new proc fs files. To fix it, we need to mark the deleting or deleted proc_dir_entry as invalid and the lookup afterwards will use the new proc_dir_entry regardless of the status of the old dentry. Signed-off-by: Hou Tao --- fs/proc/generic.c | 21 ++++++++++++++++++++- fs/proc/inode.c | 5 +++++ fs/proc/internal.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index ee27feb..92c9dd4 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -23,11 +23,19 @@ #include #include #include +#include #include "internal.h" +static int proc_dentry_revalidate(struct dentry *dentry, unsigned int flags); + static DEFINE_RWLOCK(proc_subdir_lock); +static const struct dentry_operations proc_dentry_operations = { + .d_revalidate = proc_dentry_revalidate, + .d_delete = always_delete_dentry, +}; + static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) { if (len < de->namelen) @@ -223,6 +231,17 @@ void proc_free_inum(unsigned int inum) spin_unlock_irqrestore(&proc_inum_lock, flags); } +static int proc_dentry_revalidate(struct dentry *dentry, unsigned int flags) +{ + struct proc_dir_entry *de; + + if (flags & LOOKUP_RCU) + return -ECHILD; + + de = PDE(d_inode(dentry)); + return !proc_entry_is_removing(de); +} + /* * Don't create negative dentries here, return -ENOENT by hand * instead. @@ -240,7 +259,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, inode = proc_get_inode(dir->i_sb, de); if (!inode) return ERR_PTR(-ENOMEM); - d_set_d_op(dentry, &simple_dentry_operations); + d_set_d_op(dentry, &proc_dentry_operations); d_add(dentry, inode); return NULL; } diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 2cc7a80..84232d0 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -171,6 +171,11 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) } } +bool proc_entry_is_removing(struct proc_dir_entry *de) +{ + return (atomic_read(&de->in_use) == BIAS); +} + void proc_entry_rundown(struct proc_dir_entry *de) { DECLARE_COMPLETION_ONSTACK(c); diff --git a/fs/proc/internal.h b/fs/proc/internal.h index c5ae09b..646b3f6 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -205,6 +205,7 @@ void set_proc_pid_nlink(void); extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); extern int proc_fill_super(struct super_block *, void *data, int flags); extern void proc_entry_rundown(struct proc_dir_entry *); +extern bool proc_entry_is_removing(struct proc_dir_entry *de); /* * proc_namespaces.c