Commit 3e38f30e authored by Andrew Morton's avatar Andrew Morton Committed by Jeff Garzik

[PATCH] Check for zero d_count in dget()

Patch from Maneesh Soni <maneesh@in.ibm.com>

Turns out that sysfs is doing dget() on a zero-ref dentry.  That's a bug, but
dcache is no longer detecting it.

The check was removed because with lockless d_lookup, there can be cases when
d_lookup and dput are going on concurrently, If d_lookup happens earlier then
it may do dget() on a dentry for which dput() has decremented the ref count
to zero.  This race is handled by taking the per dentry lock and checking the
DCACHE_UNHASHED flag.

The patch open-codes that part of d_lookup(), and restores the BUG check in
dget().
parent b7013f4c
...@@ -1004,8 +1004,11 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name) ...@@ -1004,8 +1004,11 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
*/ */
if (unlikely(move_count != dentry->d_move_count)) if (unlikely(move_count != dentry->d_move_count))
break; break;
if (!d_unhashed(dentry)) if (!d_unhashed(dentry)) {
found = dget(dentry); atomic_inc(&dentry->d_count);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
found = dentry;
}
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
break; break;
} }
......
...@@ -262,6 +262,8 @@ extern char * d_path(struct dentry *, struct vfsmount *, char *, int); ...@@ -262,6 +262,8 @@ extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
static __inline__ struct dentry * dget(struct dentry *dentry) static __inline__ struct dentry * dget(struct dentry *dentry)
{ {
if (dentry) { if (dentry) {
if (!atomic_read(&dentry->d_count))
BUG();
atomic_inc(&dentry->d_count); atomic_inc(&dentry->d_count);
dentry->d_vfs_flags |= DCACHE_REFERENCED; dentry->d_vfs_flags |= DCACHE_REFERENCED;
} }
......
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