diff options
Diffstat (limited to 'fs/dcache.c')
| -rw-r--r-- | fs/dcache.c | 48 |
1 files changed, 24 insertions, 24 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 75590572ff7a..9df8b861e18e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -301,6 +301,27 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
| 301 | return parent; | 301 | return parent; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | /* | ||
| 305 | * Unhash a dentry without inserting an RCU walk barrier or checking that | ||
| 306 | * dentry->d_lock is locked. The caller must take care of that, if | ||
| 307 | * appropriate. | ||
| 308 | */ | ||
| 309 | static void __d_shrink(struct dentry *dentry) | ||
| 310 | { | ||
| 311 | if (!d_unhashed(dentry)) { | ||
| 312 | struct hlist_bl_head *b; | ||
| 313 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) | ||
| 314 | b = &dentry->d_sb->s_anon; | ||
| 315 | else | ||
| 316 | b = d_hash(dentry->d_parent, dentry->d_name.hash); | ||
| 317 | |||
| 318 | hlist_bl_lock(b); | ||
| 319 | __hlist_bl_del(&dentry->d_hash); | ||
| 320 | dentry->d_hash.pprev = NULL; | ||
| 321 | hlist_bl_unlock(b); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 304 | /** | 325 | /** |
| 305 | * d_drop - drop a dentry | 326 | * d_drop - drop a dentry |
| 306 | * @dentry: dentry to drop | 327 | * @dentry: dentry to drop |
| @@ -319,17 +340,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
| 319 | void __d_drop(struct dentry *dentry) | 340 | void __d_drop(struct dentry *dentry) |
| 320 | { | 341 | { |
| 321 | if (!d_unhashed(dentry)) { | 342 | if (!d_unhashed(dentry)) { |
| 322 | struct hlist_bl_head *b; | 343 | __d_shrink(dentry); |
| 323 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) | ||
| 324 | b = &dentry->d_sb->s_anon; | ||
| 325 | else | ||
| 326 | b = d_hash(dentry->d_parent, dentry->d_name.hash); | ||
| 327 | |||
| 328 | hlist_bl_lock(b); | ||
| 329 | __hlist_bl_del(&dentry->d_hash); | ||
| 330 | dentry->d_hash.pprev = NULL; | ||
| 331 | hlist_bl_unlock(b); | ||
| 332 | |||
| 333 | dentry_rcuwalk_barrier(dentry); | 344 | dentry_rcuwalk_barrier(dentry); |
| 334 | } | 345 | } |
| 335 | } | 346 | } |
| @@ -832,10 +843,8 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 832 | BUG_ON(!IS_ROOT(dentry)); | 843 | BUG_ON(!IS_ROOT(dentry)); |
| 833 | 844 | ||
| 834 | /* detach this root from the system */ | 845 | /* detach this root from the system */ |
| 835 | spin_lock(&dentry->d_lock); | ||
| 836 | dentry_lru_del(dentry); | 846 | dentry_lru_del(dentry); |
| 837 | __d_drop(dentry); | 847 | __d_shrink(dentry); |
| 838 | spin_unlock(&dentry->d_lock); | ||
| 839 | 848 | ||
| 840 | for (;;) { | 849 | for (;;) { |
| 841 | /* descend to the first leaf in the current subtree */ | 850 | /* descend to the first leaf in the current subtree */ |
| @@ -844,16 +853,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 844 | 853 | ||
| 845 | /* this is a branch with children - detach all of them | 854 | /* this is a branch with children - detach all of them |
| 846 | * from the system in one go */ | 855 | * from the system in one go */ |
| 847 | spin_lock(&dentry->d_lock); | ||
| 848 | list_for_each_entry(loop, &dentry->d_subdirs, | 856 | list_for_each_entry(loop, &dentry->d_subdirs, |
| 849 | d_u.d_child) { | 857 | d_u.d_child) { |
| 850 | spin_lock_nested(&loop->d_lock, | ||
| 851 | DENTRY_D_LOCK_NESTED); | ||
| 852 | dentry_lru_del(loop); | 858 | dentry_lru_del(loop); |
| 853 | __d_drop(loop); | 859 | __d_shrink(loop); |
| 854 | spin_unlock(&loop->d_lock); | ||
| 855 | } | 860 | } |
| 856 | spin_unlock(&dentry->d_lock); | ||
| 857 | 861 | ||
| 858 | /* move to the first child */ | 862 | /* move to the first child */ |
| 859 | dentry = list_entry(dentry->d_subdirs.next, | 863 | dentry = list_entry(dentry->d_subdirs.next, |
| @@ -885,10 +889,8 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 885 | list_del(&dentry->d_u.d_child); | 889 | list_del(&dentry->d_u.d_child); |
| 886 | } else { | 890 | } else { |
| 887 | parent = dentry->d_parent; | 891 | parent = dentry->d_parent; |
| 888 | spin_lock(&parent->d_lock); | ||
| 889 | parent->d_count--; | 892 | parent->d_count--; |
| 890 | list_del(&dentry->d_u.d_child); | 893 | list_del(&dentry->d_u.d_child); |
| 891 | spin_unlock(&parent->d_lock); | ||
| 892 | } | 894 | } |
| 893 | 895 | ||
| 894 | inode = dentry->d_inode; | 896 | inode = dentry->d_inode; |
| @@ -935,9 +937,7 @@ void shrink_dcache_for_umount(struct super_block *sb) | |||
| 935 | 937 | ||
| 936 | dentry = sb->s_root; | 938 | dentry = sb->s_root; |
| 937 | sb->s_root = NULL; | 939 | sb->s_root = NULL; |
| 938 | spin_lock(&dentry->d_lock); | ||
| 939 | dentry->d_count--; | 940 | dentry->d_count--; |
| 940 | spin_unlock(&dentry->d_lock); | ||
| 941 | shrink_dcache_for_umount_subtree(dentry); | 941 | shrink_dcache_for_umount_subtree(dentry); |
| 942 | 942 | ||
| 943 | while (!hlist_bl_empty(&sb->s_anon)) { | 943 | while (!hlist_bl_empty(&sb->s_anon)) { |
