From: Nick Piggin <npiggin@kernel.dk>
To: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [patch 28/28] fs: consolidate dentry kill sequence
Date: Wed, 17 Nov 2010 01:09:28 +1100 [thread overview]
Message-ID: <20101116142030.902868533@kernel.dk> (raw)
In-Reply-To: 20101116140900.039761100@kernel.dk
[-- Attachment #1: dcache-consolidate-dentry-kill.patch --]
[-- Type: text/plain, Size: 5723 bytes --]
The tricky locking for disposing of a dentry is duplicated 3 times in the
dcache (dput, pruning a dentry from the LRU, and pruning its ancestors).
Consolidate them all into a single function dentry_kill.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
---
fs/dcache.c | 137 +++++++++++++++++++++++++++---------------------------------
1 file changed, 62 insertions(+), 75 deletions(-)
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2010-11-17 00:52:38.000000000 +1100
+++ linux-2.6/fs/dcache.c 2010-11-17 00:52:38.000000000 +1100
@@ -244,6 +244,40 @@ static struct dentry *d_kill(struct dent
return parent;
}
+/*
+ * Finish off a dentry we've decided to kill.
+ * dentry->d_lock must be held, returns with it unlocked.
+ * If ref is non-zero, then decrement the refcount too.
+ * Returns dentry requiring refcount drop, or NULL if we're done.
+ */
+static inline struct dentry *dentry_kill(struct dentry *dentry, int ref)
+ __releases(dentry->d_lock)
+{
+ struct dentry *parent;
+
+ if (!spin_trylock(&dcache_inode_lock)) {
+relock:
+ spin_unlock(&dentry->d_lock);
+ cpu_relax();
+ return dentry; /* try again with same dentry */
+ }
+ if (IS_ROOT(dentry))
+ parent = NULL;
+ else
+ parent = dentry->d_parent;
+ if (parent && !spin_trylock(&parent->d_lock)) {
+ spin_unlock(&dcache_inode_lock);
+ goto relock;
+ }
+ if (ref)
+ dentry->d_count--;
+ /* if dentry was on the d_lru list delete it from there */
+ dentry_lru_del(dentry);
+ /* if it was on the hash then remove it */
+ __d_drop(dentry);
+ return d_kill(dentry, parent);
+}
+
/*
* This is dput
*
@@ -269,13 +303,9 @@ static struct dentry *d_kill(struct dent
* call the dentry unlink method as well as removing it from the queues and
* releasing its resources. If the parent dentries were scheduled for release
* they too may now get deleted.
- *
- * no dcache lock, please.
*/
-
void dput(struct dentry *dentry)
{
- struct dentry *parent;
if (!dentry)
return;
@@ -308,26 +338,7 @@ void dput(struct dentry *dentry)
return;
kill_it:
- if (!spin_trylock(&dcache_inode_lock)) {
-relock:
- spin_unlock(&dentry->d_lock);
- cpu_relax();
- goto repeat;
- }
- if (IS_ROOT(dentry))
- parent = NULL;
- else
- parent = dentry->d_parent;
- if (parent && !spin_trylock(&parent->d_lock)) {
- spin_unlock(&dcache_inode_lock);
- goto relock;
- }
- dentry->d_count--;
- /* if dentry was on the d_lru list delete it from there */
- dentry_lru_del(dentry);
- /* if it was on the hash (d_delete case), then remove it */
- __d_drop(dentry);
- dentry = d_kill(dentry, parent);
+ dentry = dentry_kill(dentry, 1);
if (dentry)
goto repeat;
}
@@ -528,51 +539,43 @@ void d_prune_aliases(struct inode *inode
EXPORT_SYMBOL(d_prune_aliases);
/*
- * Throw away a dentry - free the inode, dput the parent. This requires that
- * the LRU list has already been removed.
+ * 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.
*
- * Try to prune ancestors as well. This is necessary to prevent
- * quadratic behavior of shrink_dcache_parent(), but is also expected
- * to be beneficial in reducing dentry cache fragmentation.
+ * This may fail if locks cannot be acquired no problem, just try again.
*/
-static void prune_one_dentry(struct dentry *dentry, struct dentry *parent)
+static void try_prune_one_dentry(struct dentry *dentry)
__releases(dentry->d_lock)
- __releases(parent->d_lock)
- __releases(dcache_inode_lock)
{
- __d_drop(dentry);
- dentry = d_kill(dentry, parent);
+ struct dentry *parent;
+ parent = dentry_kill(dentry, 0);
/*
- * Prune ancestors.
+ * 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;
+ if (parent == dentry)
+ return;
+
+ /* Prune ancestors. */
+ dentry = parent;
while (dentry) {
-relock:
spin_lock(&dentry->d_lock);
if (dentry->d_count > 1) {
dentry->d_count--;
spin_unlock(&dentry->d_lock);
- return;
- }
- if (!spin_trylock(&dcache_inode_lock)) {
-relock2:
- spin_unlock(&dentry->d_lock);
- cpu_relax();
- goto relock;
+ return;
}
-
- if (IS_ROOT(dentry))
- parent = NULL;
- else
- parent = dentry->d_parent;
- if (parent && !spin_trylock(&parent->d_lock)) {
- spin_unlock(&dcache_inode_lock);
- goto relock2;
- }
- dentry->d_count--;
- dentry_lru_del(dentry);
- __d_drop(dentry);
- dentry = d_kill(dentry, parent);
+ dentry = dentry_kill(dentry, 1);
}
}
@@ -582,8 +585,6 @@ static void shrink_dentry_list(struct li
rcu_read_lock();
while (!list_empty(list)) {
- struct dentry *parent;
-
dentry = list_entry(list->prev, struct dentry, d_lru);
/* Don't need RCU dereference because we recheck under lock */
@@ -604,24 +605,10 @@ static void shrink_dentry_list(struct li
continue;
}
- if (!spin_trylock(&dcache_inode_lock)) {
-relock:
- spin_unlock(&dentry->d_lock);
- cpu_relax();
- continue;
- }
- if (IS_ROOT(dentry))
- parent = NULL;
- else
- parent = dentry->d_parent;
- if (parent && !spin_trylock(&parent->d_lock)) {
- spin_unlock(&dcache_inode_lock);
- goto relock;
- }
- dentry_lru_del(dentry);
-
rcu_read_unlock();
- prune_one_dentry(dentry, parent);
+
+ try_prune_one_dentry(dentry);
+
rcu_read_lock();
}
rcu_read_unlock();
next prev parent reply other threads:[~2010-11-16 14:24 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-16 14:09 [patch 00/28] [rfc] dcache scaling part 1 Nick Piggin
2010-11-16 14:09 ` [patch 01/28] fs: d_validate fixes Nick Piggin
2010-11-17 10:44 ` Andi Kleen
2010-11-17 10:44 ` Andi Kleen
2010-11-18 20:51 ` David Miller
2010-11-18 20:59 ` David Miller
2010-11-19 5:05 ` Nick Piggin
2010-11-19 5:01 ` Nick Piggin
2010-11-16 14:09 ` [patch 02/28] kernel: kmem_ptr_validate considered harmful Nick Piggin
2010-11-16 14:09 ` [patch 03/28] fs: dcache documentation cleanup Nick Piggin
2010-11-16 14:09 ` [patch 04/28] fs: change d_delete semantics Nick Piggin
2010-11-17 0:16 ` Tim Pepper
2010-11-16 14:09 ` [patch 05/28] cifs: dont overwrite dentry name in d_revalidate Nick Piggin
2010-11-16 14:09 ` [patch 06/28] jfs: " Nick Piggin
2010-11-16 14:09 ` [patch 07/28] fs: change d_compare for rcu-walk Nick Piggin
2010-11-17 0:44 ` Tim Pepper
2010-11-16 14:09 ` [patch 08/28] fs: change d_hash " Nick Piggin
2010-11-17 0:50 ` Tim Pepper
2010-11-16 14:09 ` [patch 09/28] hostfs: simplify locking Nick Piggin
2010-11-16 14:09 ` [patch 10/28] fs: dcache scale hash Nick Piggin
2010-11-16 14:09 ` [patch 11/28] fs: dcache scale lru Nick Piggin
2010-11-16 14:09 ` [patch 12/28] fs: dcache scale dentry refcount Nick Piggin
2010-11-16 14:09 ` [patch 13/28] fs: dcache scale d_unhashed Nick Piggin
2010-11-19 19:41 ` Tim Pepper
2010-11-16 14:09 ` [patch 14/28] fs: dcache scale subdirs Nick Piggin
2010-11-19 19:41 ` Tim Pepper
2010-11-19 19:41 ` Tim Pepper
2010-11-16 14:09 ` [patch 15/28] fs: scale inode alias list Nick Piggin
2010-11-19 19:41 ` Tim Pepper
2010-11-19 19:41 ` Tim Pepper
2010-11-16 14:09 ` [patch 16/28] fs: Use rename lock and RCU for multi-step operations Nick Piggin
2010-11-19 19:42 ` Tim Pepper
2010-11-16 14:09 ` [patch 17/28] fs: increase d_name lock coverage Nick Piggin
2010-11-16 14:09 ` [patch 18/28] fs: dcache remove dcache_lock Nick Piggin
2010-11-16 14:09 ` [patch 19/28] fs: dcache avoid starvation in dcache multi-step operations Nick Piggin
2010-11-16 14:09 ` [patch 20/28] fs: dcache reduce dput locking Nick Piggin
2010-11-16 14:09 ` [patch 21/28] fs: dcache reduce locking in d_alloc Nick Piggin
2010-11-16 14:09 ` [patch 22/28] fs: dcache reduce dcache_inode_lock Nick Piggin
2010-11-16 14:09 ` [patch 23/28] fs: dcache rationalise dget variants Nick Piggin
2010-11-16 14:09 ` [patch 24/28] fs: dcache reduce d_parent locking Nick Piggin
2010-11-16 14:09 ` [patch 25/28] fs: dcache reduce prune_one_dentry locking Nick Piggin
2010-11-16 14:09 ` [patch 26/28] fs: reduce dcache_inode_lock width in lru scanning Nick Piggin
2010-11-16 14:09 ` [patch 27/28] fs: use RCU in shrink_dentry_list to reduce lock nesting Nick Piggin
2010-11-16 14:09 ` Nick Piggin [this message]
2010-11-17 2:12 ` [patch 00/28] [rfc] dcache scaling part 1 Dave Chinner
2010-11-17 10:56 ` Andi Kleen
2010-11-17 11:19 ` Nick Piggin
2010-11-17 12:01 ` Andi Kleen
2010-11-19 19:43 ` Tim Pepper
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101116142030.902868533@kernel.dk \
--to=npiggin@kernel.dk \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.