diff options
| -rw-r--r-- | fs/dcache.c | 27 |
1 files changed, 4 insertions, 23 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 2321e1a861f6..42ae01eefc07 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -796,23 +796,9 @@ static void shrink_dentry_list(struct list_head *list) | |||
| 796 | { | 796 | { |
| 797 | struct dentry *dentry, *parent; | 797 | struct dentry *dentry, *parent; |
| 798 | 798 | ||
| 799 | rcu_read_lock(); | 799 | while (!list_empty(list)) { |
| 800 | for (;;) { | 800 | dentry = list_entry(list->prev, struct dentry, d_lru); |
| 801 | dentry = list_entry_rcu(list->prev, struct dentry, d_lru); | ||
| 802 | if (&dentry->d_lru == list) | ||
| 803 | break; /* empty */ | ||
| 804 | |||
| 805 | /* | ||
| 806 | * Get the dentry lock, and re-verify that the dentry is | ||
| 807 | * this on the shrinking list. If it is, we know that | ||
| 808 | * DCACHE_SHRINK_LIST and DCACHE_LRU_LIST are set. | ||
| 809 | */ | ||
| 810 | spin_lock(&dentry->d_lock); | 801 | spin_lock(&dentry->d_lock); |
| 811 | if (dentry != list_entry(list->prev, struct dentry, d_lru)) { | ||
| 812 | spin_unlock(&dentry->d_lock); | ||
| 813 | continue; | ||
| 814 | } | ||
| 815 | |||
| 816 | /* | 802 | /* |
| 817 | * The dispose list is isolated and dentries are not accounted | 803 | * The dispose list is isolated and dentries are not accounted |
| 818 | * to the LRU here, so we can simply remove it from the list | 804 | * to the LRU here, so we can simply remove it from the list |
| @@ -828,23 +814,20 @@ static void shrink_dentry_list(struct list_head *list) | |||
| 828 | spin_unlock(&dentry->d_lock); | 814 | spin_unlock(&dentry->d_lock); |
| 829 | continue; | 815 | continue; |
| 830 | } | 816 | } |
| 831 | rcu_read_unlock(); | ||
| 832 | 817 | ||
| 833 | parent = dentry_kill(dentry, 0); | 818 | parent = dentry_kill(dentry, 0); |
| 834 | /* | 819 | /* |
| 835 | * If dentry_kill returns NULL, we have nothing more to do. | 820 | * If dentry_kill returns NULL, we have nothing more to do. |
| 836 | */ | 821 | */ |
| 837 | if (!parent) { | 822 | if (!parent) |
| 838 | rcu_read_lock(); | ||
| 839 | continue; | 823 | continue; |
| 840 | } | 824 | |
| 841 | if (unlikely(parent == dentry)) { | 825 | if (unlikely(parent == dentry)) { |
| 842 | /* | 826 | /* |
| 843 | * trylocks have failed and d_lock has been held the | 827 | * trylocks have failed and d_lock has been held the |
| 844 | * whole time, so it could not have been added to any | 828 | * whole time, so it could not have been added to any |
| 845 | * other lists. Just add it back to the shrink list. | 829 | * other lists. Just add it back to the shrink list. |
| 846 | */ | 830 | */ |
| 847 | rcu_read_lock(); | ||
| 848 | d_shrink_add(dentry, list); | 831 | d_shrink_add(dentry, list); |
| 849 | spin_unlock(&dentry->d_lock); | 832 | spin_unlock(&dentry->d_lock); |
| 850 | continue; | 833 | continue; |
| @@ -858,9 +841,7 @@ static void shrink_dentry_list(struct list_head *list) | |||
| 858 | dentry = parent; | 841 | dentry = parent; |
| 859 | while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) | 842 | while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) |
| 860 | dentry = dentry_kill(dentry, 1); | 843 | dentry = dentry_kill(dentry, 1); |
| 861 | rcu_read_lock(); | ||
| 862 | } | 844 | } |
| 863 | rcu_read_unlock(); | ||
| 864 | } | 845 | } |
| 865 | 846 | ||
| 866 | static enum lru_status | 847 | static enum lru_status |
