Btrfs: use dget_parent where we can UPDATED
There are lots of places where we do dentry->d_parent->d_inode without holding the dentry->d_lock. This could cause problems with rename. So instead we need to use dget_parent() and hold the reference to the parent as long as we are going to use it's inode and then dput it at the end. Signed-off-by: Josef Bacik <josef@redhat.com> Cc: raven@themaw.net Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
@@ -2869,6 +2869,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
int ret = 0;
|
||||
struct btrfs_root *root;
|
||||
struct dentry *old_parent = NULL;
|
||||
|
||||
/*
|
||||
* for regular files, if its inode is already on disk, we don't
|
||||
@@ -2910,10 +2911,13 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
|
||||
if (IS_ROOT(parent))
|
||||
break;
|
||||
|
||||
parent = parent->d_parent;
|
||||
parent = dget_parent(parent);
|
||||
dput(old_parent);
|
||||
old_parent = parent;
|
||||
inode = parent->d_inode;
|
||||
|
||||
}
|
||||
dput(old_parent);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -2945,6 +2949,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL;
|
||||
struct super_block *sb;
|
||||
struct dentry *old_parent = NULL;
|
||||
int ret = 0;
|
||||
u64 last_committed = root->fs_info->last_trans_committed;
|
||||
|
||||
@@ -3016,10 +3021,13 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
|
||||
if (IS_ROOT(parent))
|
||||
break;
|
||||
|
||||
parent = parent->d_parent;
|
||||
parent = dget_parent(parent);
|
||||
dput(old_parent);
|
||||
old_parent = parent;
|
||||
}
|
||||
ret = 0;
|
||||
end_trans:
|
||||
dput(old_parent);
|
||||
if (ret < 0) {
|
||||
BUG_ON(ret != -ENOSPC);
|
||||
root->fs_info->last_trans_log_full_commit = trans->transid;
|
||||
@@ -3039,8 +3047,13 @@ end_no_trans:
|
||||
int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct dentry *dentry)
|
||||
{
|
||||
return btrfs_log_inode_parent(trans, root, dentry->d_inode,
|
||||
dentry->d_parent, 0);
|
||||
struct dentry *parent = dget_parent(dentry);
|
||||
int ret;
|
||||
|
||||
ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent, 0);
|
||||
dput(parent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user