summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2011-06-07 14:09:30 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2011-08-01 02:27:57 -0400
commit43c1c9cd244098012441b90c32304f11f1258d43 (patch)
treef6d924936b376cfa3bb7bc1eec5716900a61a2cf
parentc6627c60c07c43b51ef88e352627fa786d1e1592 (diff)
VFS: Reorganise shrink_dcache_for_umount_subtree() after demise of dcache_lock
Reorganise shrink_dcache_for_umount_subtree() in light of the demise of dcache_lock. Without that dcache_lock, there is no need for the batching of removal of dentries from the system under it (we wanted to make intensive use of the locked data whilst we held it, but didn't want to hold it for long at a time). This works, provided the preceding patch is correct in its removal of locking on dentry->d_lock on the basis that no one should be locking these dentries any more as the whole superblock is defunct. With this patch, the calls to dentry_lru_del() and __d_shrink() are placed at the point where each dentry is detached handled. It is possible that, as an alternative, the batching should still be done - but only for dentry_lru_del() of all a dentry's children in one go. In such a case, the batching would be done under dcache_lru_lock. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/dcache.c22
1 files changed, 5 insertions, 17 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 9df8b861e18..2347cdb15ab 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -842,33 +842,21 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
BUG_ON(!IS_ROOT(dentry));
- /* detach this root from the system */
- dentry_lru_del(dentry);
- __d_shrink(dentry);
-
for (;;) {
/* descend to the first leaf in the current subtree */
- while (!list_empty(&dentry->d_subdirs)) {
- struct dentry *loop;
-
- /* this is a branch with children - detach all of them
- * from the system in one go */
- list_for_each_entry(loop, &dentry->d_subdirs,
- d_u.d_child) {
- dentry_lru_del(loop);
- __d_shrink(loop);
- }
-
- /* move to the first child */
+ while (!list_empty(&dentry->d_subdirs))
dentry = list_entry(dentry->d_subdirs.next,
struct dentry, d_u.d_child);
- }
/* consume the dentries from this leaf up through its parents
* until we find one with children or run out altogether */
do {
struct inode *inode;
+ /* detach from the system */
+ dentry_lru_del(dentry);
+ __d_shrink(dentry);
+
if (dentry->d_count != 0) {
printk(KERN_ERR
"BUG: Dentry %p{i=%lx,n=%s}"