Commit 2e4bfab9 authored by Yan, Zheng's avatar Yan, Zheng Committed by Chris Mason

Btrfs: Avoid orphan inodes cleanup during committing transaction

btrfs_lookup_dentry may trigger orphan cleanup, so it's not good
to call it while committing a transaction.
Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent c71bf099
...@@ -237,7 +237,6 @@ static noinline int create_subvol(struct btrfs_root *root, ...@@ -237,7 +237,6 @@ static noinline int create_subvol(struct btrfs_root *root,
u64 objectid; u64 objectid;
u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
u64 index = 0; u64 index = 0;
unsigned long nr = 1;
/* /*
* 1 - inode item * 1 - inode item
...@@ -342,24 +341,21 @@ static noinline int create_subvol(struct btrfs_root *root, ...@@ -342,24 +341,21 @@ static noinline int create_subvol(struct btrfs_root *root,
d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
fail: fail:
nr = trans->blocks_used;
err = btrfs_commit_transaction(trans, root); err = btrfs_commit_transaction(trans, root);
if (err && !ret) if (err && !ret)
ret = err; ret = err;
btrfs_unreserve_metadata_space(root, 6); btrfs_unreserve_metadata_space(root, 6);
btrfs_btree_balance_dirty(root, nr);
return ret; return ret;
} }
static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
char *name, int namelen) char *name, int namelen)
{ {
struct inode *inode;
struct btrfs_pending_snapshot *pending_snapshot; struct btrfs_pending_snapshot *pending_snapshot;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret = 0; int ret;
int err;
unsigned long nr = 0;
if (!root->ref_cows) if (!root->ref_cows)
return -EINVAL; return -EINVAL;
...@@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, ...@@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
*/ */
ret = btrfs_reserve_metadata_space(root, 6); ret = btrfs_reserve_metadata_space(root, 6);
if (ret) if (ret)
goto fail_unlock; goto fail;
pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
if (!pending_snapshot) { if (!pending_snapshot) {
ret = -ENOMEM; ret = -ENOMEM;
btrfs_unreserve_metadata_space(root, 6); btrfs_unreserve_metadata_space(root, 6);
goto fail_unlock; goto fail;
} }
pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS);
if (!pending_snapshot->name) { if (!pending_snapshot->name) {
ret = -ENOMEM; ret = -ENOMEM;
kfree(pending_snapshot); kfree(pending_snapshot);
btrfs_unreserve_metadata_space(root, 6); btrfs_unreserve_metadata_space(root, 6);
goto fail_unlock; goto fail;
} }
memcpy(pending_snapshot->name, name, namelen); memcpy(pending_snapshot->name, name, namelen);
pending_snapshot->name[namelen] = '\0'; pending_snapshot->name[namelen] = '\0';
...@@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, ...@@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
pending_snapshot->root = root; pending_snapshot->root = root;
list_add(&pending_snapshot->list, list_add(&pending_snapshot->list,
&trans->transaction->pending_snapshots); &trans->transaction->pending_snapshots);
err = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
BUG_ON(ret);
btrfs_unreserve_metadata_space(root, 6);
fail_unlock: inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
btrfs_btree_balance_dirty(root, nr); if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
goto fail;
}
BUG_ON(!inode);
d_instantiate(dentry, inode);
ret = 0;
fail:
return ret; return ret;
} }
......
...@@ -796,7 +796,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -796,7 +796,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
memcpy(&pending->root_key, &key, sizeof(key)); memcpy(&pending->root_key, &key, sizeof(key));
fail: fail:
kfree(new_root_item); kfree(new_root_item);
btrfs_unreserve_metadata_space(root, 6);
return ret; return ret;
} }
...@@ -808,7 +807,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, ...@@ -808,7 +807,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
u64 index = 0; u64 index = 0;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct inode *parent_inode; struct inode *parent_inode;
struct inode *inode;
struct btrfs_root *parent_root; struct btrfs_root *parent_root;
parent_inode = pending->dentry->d_parent->d_inode; parent_inode = pending->dentry->d_parent->d_inode;
...@@ -840,8 +838,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, ...@@ -840,8 +838,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
BUG_ON(ret); BUG_ON(ret);
inode = btrfs_lookup_dentry(parent_inode, pending->dentry);
d_instantiate(pending->dentry, inode);
fail: fail:
btrfs_end_transaction(trans, fs_info->fs_root); btrfs_end_transaction(trans, fs_info->fs_root);
return ret; return ret;
......
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