diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:49:47 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:25 -0500 |
commit | ec33679d78f9d653a44ddba10b5fb824c06330a1 (patch) | |
tree | 5d1530286d1348064020c466427576294def7191 /fs/dcache.c | |
parent | be182bff72fae6a3eb25624b39170c40b72f0909 (diff) |
fs: use RCU in shrink_dentry_list to reduce lock nesting
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index fe8f28a2878e..d1840b30c673 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -615,16 +615,16 @@ static void shrink_dentry_list(struct list_head *list) | |||
615 | { | 615 | { |
616 | struct dentry *dentry; | 616 | struct dentry *dentry; |
617 | 617 | ||
618 | while (!list_empty(list)) { | 618 | rcu_read_lock(); |
619 | for (;;) { | ||
619 | struct dentry *parent; | 620 | struct dentry *parent; |
620 | 621 | ||
621 | dentry = list_entry(list->prev, struct dentry, d_lru); | 622 | dentry = list_entry_rcu(list->prev, struct dentry, d_lru); |
622 | 623 | if (&dentry->d_lru == list) | |
623 | if (!spin_trylock(&dentry->d_lock)) { | 624 | break; /* empty */ |
624 | relock1: | 625 | spin_lock(&dentry->d_lock); |
625 | spin_unlock(&dcache_lru_lock); | 626 | if (dentry != list_entry(list->prev, struct dentry, d_lru)) { |
626 | cpu_relax(); | 627 | spin_unlock(&dentry->d_lock); |
627 | spin_lock(&dcache_lru_lock); | ||
628 | continue; | 628 | continue; |
629 | } | 629 | } |
630 | 630 | ||
@@ -634,14 +634,16 @@ relock1: | |||
634 | * it - just keep it off the LRU list. | 634 | * it - just keep it off the LRU list. |
635 | */ | 635 | */ |
636 | if (dentry->d_count) { | 636 | if (dentry->d_count) { |
637 | __dentry_lru_del(dentry); | 637 | dentry_lru_del(dentry); |
638 | spin_unlock(&dentry->d_lock); | 638 | spin_unlock(&dentry->d_lock); |
639 | continue; | 639 | continue; |
640 | } | 640 | } |
641 | |||
641 | if (!spin_trylock(&dcache_inode_lock)) { | 642 | if (!spin_trylock(&dcache_inode_lock)) { |
642 | relock2: | 643 | relock: |
643 | spin_unlock(&dentry->d_lock); | 644 | spin_unlock(&dentry->d_lock); |
644 | goto relock1; | 645 | cpu_relax(); |
646 | continue; | ||
645 | } | 647 | } |
646 | if (IS_ROOT(dentry)) | 648 | if (IS_ROOT(dentry)) |
647 | parent = NULL; | 649 | parent = NULL; |
@@ -649,15 +651,15 @@ relock2: | |||
649 | parent = dentry->d_parent; | 651 | parent = dentry->d_parent; |
650 | if (parent && !spin_trylock(&parent->d_lock)) { | 652 | if (parent && !spin_trylock(&parent->d_lock)) { |
651 | spin_unlock(&dcache_inode_lock); | 653 | spin_unlock(&dcache_inode_lock); |
652 | goto relock2; | 654 | goto relock; |
653 | } | 655 | } |
654 | __dentry_lru_del(dentry); | 656 | dentry_lru_del(dentry); |
655 | spin_unlock(&dcache_lru_lock); | ||
656 | 657 | ||
658 | rcu_read_unlock(); | ||
657 | prune_one_dentry(dentry, parent); | 659 | prune_one_dentry(dentry, parent); |
658 | /* dcache_inode_lock and dentry->d_lock dropped */ | 660 | rcu_read_lock(); |
659 | spin_lock(&dcache_lru_lock); | ||
660 | } | 661 | } |
662 | rcu_read_unlock(); | ||
661 | } | 663 | } |
662 | 664 | ||
663 | /** | 665 | /** |
@@ -705,15 +707,15 @@ relock: | |||
705 | if (!--cnt) | 707 | if (!--cnt) |
706 | break; | 708 | break; |
707 | } | 709 | } |
708 | /* XXX: re-add cond_resched_lock when dcache_lock goes away */ | 710 | cond_resched_lock(&dcache_lru_lock); |
709 | } | 711 | } |
710 | |||
711 | *count = cnt; | ||
712 | shrink_dentry_list(&tmp); | ||
713 | |||
714 | if (!list_empty(&referenced)) | 712 | if (!list_empty(&referenced)) |
715 | list_splice(&referenced, &sb->s_dentry_lru); | 713 | list_splice(&referenced, &sb->s_dentry_lru); |
716 | spin_unlock(&dcache_lru_lock); | 714 | spin_unlock(&dcache_lru_lock); |
715 | |||
716 | shrink_dentry_list(&tmp); | ||
717 | |||
718 | *count = cnt; | ||
717 | } | 719 | } |
718 | 720 | ||
719 | /** | 721 | /** |
@@ -805,7 +807,9 @@ void shrink_dcache_sb(struct super_block *sb) | |||
805 | spin_lock(&dcache_lru_lock); | 807 | spin_lock(&dcache_lru_lock); |
806 | while (!list_empty(&sb->s_dentry_lru)) { | 808 | while (!list_empty(&sb->s_dentry_lru)) { |
807 | list_splice_init(&sb->s_dentry_lru, &tmp); | 809 | list_splice_init(&sb->s_dentry_lru, &tmp); |
810 | spin_unlock(&dcache_lru_lock); | ||
808 | shrink_dentry_list(&tmp); | 811 | shrink_dentry_list(&tmp); |
812 | spin_lock(&dcache_lru_lock); | ||
809 | } | 813 | } |
810 | spin_unlock(&dcache_lru_lock); | 814 | spin_unlock(&dcache_lru_lock); |
811 | } | 815 | } |