Commit a66e7cc6 authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: only clear the need lookup flag after the dentry is setup

We can race with readdir and the RCU path walking stuff.  This is because we
clear the need lookup flag before actually instantiating the inode.  This will
lead the RCU path walk stuff to find a dentry it thinks is valid without a
d_inode attached.  So instead unhash the dentry when we first start the lookup,
and then clear the flag after we've instantiated the dentry so we're garunteed
to either try the slow lookup, or have the d_inode set properly.
Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 48802c8a
...@@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) ...@@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key)); memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
kfree(dentry->d_fsdata); kfree(dentry->d_fsdata);
dentry->d_fsdata = NULL; dentry->d_fsdata = NULL;
d_clear_need_lookup(dentry); /* This thing is hashed, drop it for now */
d_drop(dentry);
} else { } else {
ret = btrfs_inode_by_name(dir, dentry, &location); ret = btrfs_inode_by_name(dir, dentry, &location);
} }
...@@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry) ...@@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry)
static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd) struct nameidata *nd)
{ {
return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); struct dentry *ret;
ret = d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry);
if (unlikely(d_need_lookup(dentry))) {
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
spin_unlock(&dentry->d_lock);
}
return ret;
} }
unsigned char btrfs_filetype_table[] = { unsigned char btrfs_filetype_table[] = {
......
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