aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:45 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:25 -0500
commit89e6054836a7b1e7500cd70a14b5579e752c9250 (patch)
treeb74d2ecd1ac2a571d289e5525a0dc067ec1f35eb
parenta734eb458ab2bd11479a27dd54f48e1b26a55845 (diff)
fs: dcache reduce prune_one_dentry locking
prune_one_dentry can avoid quite a bit of locking in the common case where ancestors have an elevated refcount. Alternatively, we could have gone the other way and made fewer trylocks in the case where d_count goes to zero, but is probably less common. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
-rw-r--r--fs/dcache.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index a8f89765d602..195706374697 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -582,26 +582,29 @@ static void prune_one_dentry(struct dentry *dentry, struct dentry *parent)
582 * Prune ancestors. 582 * Prune ancestors.
583 */ 583 */
584 while (dentry) { 584 while (dentry) {
585 spin_lock(&dcache_inode_lock); 585relock:
586again:
587 spin_lock(&dentry->d_lock); 586 spin_lock(&dentry->d_lock);
587 if (dentry->d_count > 1) {
588 dentry->d_count--;
589 spin_unlock(&dentry->d_lock);
590 return;
591 }
592 if (!spin_trylock(&dcache_inode_lock)) {
593relock2:
594 spin_unlock(&dentry->d_lock);
595 cpu_relax();
596 goto relock;
597 }
598
588 if (IS_ROOT(dentry)) 599 if (IS_ROOT(dentry))
589 parent = NULL; 600 parent = NULL;
590 else 601 else
591 parent = dentry->d_parent; 602 parent = dentry->d_parent;
592 if (parent && !spin_trylock(&parent->d_lock)) { 603 if (parent && !spin_trylock(&parent->d_lock)) {
593 spin_unlock(&dentry->d_lock);
594 goto again;
595 }
596 dentry->d_count--;
597 if (dentry->d_count) {
598 if (parent)
599 spin_unlock(&parent->d_lock);
600 spin_unlock(&dentry->d_lock);
601 spin_unlock(&dcache_inode_lock); 604 spin_unlock(&dcache_inode_lock);
602 return; 605 goto relock2;
603 } 606 }
604 607 dentry->d_count--;
605 dentry_lru_del(dentry); 608 dentry_lru_del(dentry);
606 __d_drop(dentry); 609 __d_drop(dentry);
607 dentry = d_kill(dentry, parent); 610 dentry = d_kill(dentry, parent);