Commit f8713576 authored by David Howells's avatar David Howells Committed by Linus Torvalds

[PATCH] VFS: Fix an error in unused dentry counting

With Vasily Averin <vvs@sw.ru>

Fix an error in unused dentry counting in shrink_dcache_for_umount_subtree()
in which the count is modified without the dcache_lock held.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Cc: Vasily Averin <vvs@sw.ru>
Cc: Neil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6eac3f93
...@@ -557,6 +557,7 @@ void shrink_dcache_sb(struct super_block * sb) ...@@ -557,6 +557,7 @@ void shrink_dcache_sb(struct super_block * sb)
static void shrink_dcache_for_umount_subtree(struct dentry *dentry) static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
{ {
struct dentry *parent; struct dentry *parent;
unsigned detached = 0;
BUG_ON(!IS_ROOT(dentry)); BUG_ON(!IS_ROOT(dentry));
...@@ -621,7 +622,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) ...@@ -621,7 +622,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
atomic_dec(&parent->d_count); atomic_dec(&parent->d_count);
list_del(&dentry->d_u.d_child); list_del(&dentry->d_u.d_child);
dentry_stat.nr_dentry--; /* For d_free, below */ detached++;
inode = dentry->d_inode; inode = dentry->d_inode;
if (inode) { if (inode) {
...@@ -639,7 +640,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) ...@@ -639,7 +640,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
* otherwise we ascend to the parent and move to the * otherwise we ascend to the parent and move to the
* next sibling if there is one */ * next sibling if there is one */
if (!parent) if (!parent)
return; goto out;
dentry = parent; dentry = parent;
...@@ -648,6 +649,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) ...@@ -648,6 +649,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
dentry = list_entry(dentry->d_subdirs.next, dentry = list_entry(dentry->d_subdirs.next,
struct dentry, d_u.d_child); struct dentry, d_u.d_child);
} }
out:
/* several dentries were freed, need to correct nr_dentry */
spin_lock(&dcache_lock);
dentry_stat.nr_dentry -= detached;
spin_unlock(&dcache_lock);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment