This closes the race in ->hide where we could sometimes end up with two
hashed negative dentries for the same name, using the method we
discussed on irc. As you observed, we do not need the HIDDEN flag any
more because when a negative dentry is deferred, its inode is always
zero:
- If it has a single reference, d_delete sets the inode to zero.
- If it has multiple references (busy) then we defer a clone,
one of the other holders takes care of reducing the inode count.
So now we can get rid of about half the patch, that implements the
HIDDEN bit that we just got rid of :)
Diff against the previous version attached, does not remove the HIDDEN
bit yet.
Regards,
Daniel
diff --git a/fs/dcache.c b/fs/dcache.c
index 038bb83..0cb1f71 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1408,7 +1408,7 @@ void d_delete(struct dentry * dentry)
return;
}
- if (!d_unhashed(dentry) && !hidden)
+ if (!d_unhashed(dentry))
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index b7bb8a8..1263cc8 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -292,8 +292,6 @@ int ext2_flush_dir(struct dentry *dir)
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
real_unlink(dir->d_inode, dentry);
- if (dentry->d_inode)
- d_delete(dentry);
dput(dentry);
spin_lock(&dcache_lock);
continue;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index a90bd96..19cdbb4 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -38,6 +38,7 @@
static int ext2_hide_dentry(struct dentry *dentry)
{
+ struct dentry *clone;
dentry->d_flags |= DCACHE_HIDDEN;
if (!(dentry->d_flags & DCACHE_BACKED)) {
/* converting unbacked to negative */
@@ -52,15 +53,17 @@ static int ext2_hide_dentry(struct dentry *dentry)
dget(dentry);
return 1;
}
+ show_dentry("busy dentry", dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
- dentry = d_alloc(dentry->d_parent, &dentry->d_name);
- dentry->d_flags |= DCACHE_STALE;
- d_instantiate(dentry, NULL);
- d_rehash(dentry);
+ clone = d_alloc(dentry->d_parent, &dentry->d_name);
+ show_dentry("clone dentry", clone);
+ clone->d_flags |= DCACHE_STALE;
+ d_instantiate(clone, NULL);
+ d_rehash(clone);
spin_lock(&dentry->d_lock);
spin_lock(&dcache_lock);
- return 0;
+ return atomic_read(&dentry->d_count) == 1;
}
static struct dentry_operations ext2_dentry_operations = {
_______________________________________________
Tux3 mailing list
[email protected]
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3