From patchwork Thu Aug 13 21:23:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Nicholas A. Bellinger" X-Patchwork-Id: 7011011 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 744E3C05AC for ; Thu, 13 Aug 2015 21:29:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BB065205FE for ; Thu, 13 Aug 2015 21:29:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C49EC205C1 for ; Thu, 13 Aug 2015 21:29:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754220AbbHMV3F (ORCPT ); Thu, 13 Aug 2015 17:29:05 -0400 Received: from mail.linux-iscsi.org ([67.23.28.174]:36964 "EHLO linux-iscsi.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754171AbbHMV3E (ORCPT ); Thu, 13 Aug 2015 17:29:04 -0400 Received: from linux-iscsi.org (localhost [127.0.0.1]) by linux-iscsi.org (Postfix) with ESMTP id D566D22DA53; Thu, 13 Aug 2015 21:23:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=linux-iscsi.org; s=default.private; t=1439501031; bh=+rrkpdqr9jI0AJkaWrq5zmjjyxbF3AQ BEnkqLkoQeiE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To: References; b=LBHoajc4khSSQeyXYeV52tI8uwMbShiJKPuScDDpYB7xDUHAZLap nIGKxXDR1cKSQD55lWNxCeeWIhEsyxUVJ7pFhUurCkgL3SxFyxnB68bfKIRUiU6CgPK cMMQsbu8NQw+XyPKkAWDqH8XWd1xwOsLdGtR21Si7q8ZZjlmuKhU= From: "Nicholas A. Bellinger" To: stable Cc: Greg-KH , Al Viro , Miklos Szeredi , linux-fsdevel Subject: [PATCH-v3.14.y 2/8] fold try_prune_one_dentry() Date: Thu, 13 Aug 2015 21:23:40 +0000 Message-Id: <1439501026-19955-3-git-send-email-nab@linux-iscsi.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1439501026-19955-1-git-send-email-nab@linux-iscsi.org> References: <1439501026-19955-1-git-send-email-nab@linux-iscsi.org> 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.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham 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 From: Al Viro commit 5c47e6d0ad608987b91affbcf7d1fc12dfbe8fb4 upstream. Signed-off-by: Al Viro --- fs/dcache.c | 75 +++++++++++++++++++++---------------------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 8b5adab..1dc738a 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -788,47 +788,9 @@ restart: } EXPORT_SYMBOL(d_prune_aliases); -/* - * Try to throw away a dentry - free the inode, dput the parent. - * Requires dentry->d_lock is held, and dentry->d_count == 0. - * Releases dentry->d_lock. - * - * This may fail if locks cannot be acquired no problem, just try again. - */ -static struct dentry * try_prune_one_dentry(struct dentry *dentry) - __releases(dentry->d_lock) -{ - struct dentry *parent; - - parent = dentry_kill(dentry, 0); - /* - * If dentry_kill returns NULL, we have nothing more to do. - * if it returns the same dentry, trylocks failed. In either - * case, just loop again. - * - * Otherwise, we need to prune ancestors too. This is necessary - * to prevent quadratic behavior of shrink_dcache_parent(), but - * is also expected to be beneficial in reducing dentry cache - * fragmentation. - */ - if (!parent) - return NULL; - if (parent == dentry) - return dentry; - - /* Prune ancestors. */ - dentry = parent; - while (dentry) { - if (lockref_put_or_lock(&dentry->d_lockref)) - return NULL; - dentry = dentry_kill(dentry, 1); - } - return NULL; -} - static void shrink_dentry_list(struct list_head *list) { - struct dentry *dentry; + struct dentry *dentry, *parent; rcu_read_lock(); for (;;) { @@ -864,22 +826,35 @@ static void shrink_dentry_list(struct list_head *list) } rcu_read_unlock(); + parent = dentry_kill(dentry, 0); /* - * If 'try_to_prune()' returns a dentry, it will - * be the same one we passed in, and d_lock will - * have been held the whole time, so it will not - * have been added to any other lists. We failed - * to get the inode lock. - * - * We just add it back to the shrink list. + * If dentry_kill returns NULL, we have nothing more to do. */ - dentry = try_prune_one_dentry(dentry); - - rcu_read_lock(); - if (dentry) { + if (!parent) { + rcu_read_lock(); + continue; + } + if (unlikely(parent == dentry)) { + /* + * trylocks have failed and d_lock has been held the + * whole time, so it could not have been added to any + * other lists. Just add it back to the shrink list. + */ + rcu_read_lock(); d_shrink_add(dentry, list); spin_unlock(&dentry->d_lock); + continue; } + /* + * We need to prune ancestors too. This is necessary to prevent + * quadratic behavior of shrink_dcache_parent(), but is also + * expected to be beneficial in reducing dentry cache + * fragmentation. + */ + dentry = parent; + while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) + dentry = dentry_kill(dentry, 1); + rcu_read_lock(); } rcu_read_unlock(); }