diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2009-01-06 09:58:06 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-01-06 09:58:06 -0500 |
commit | 180591bcfed1a2cec048abb21d3dab840625caab (patch) | |
tree | 9bd247570ef8f3ed33afcb25bb365ccd707c8a73 /fs | |
parent | 9ca03b997f71787e345951e6267fbd8eba14d49f (diff) |
Btrfs: Use btrfs_join_transaction to avoid deadlocks during snapshot creation
Snapshot creation happens at a specific time during transaction commit. We
need to make sure the code called by snapshot creation doesn't wait
for the running transaction to commit.
This changes btrfs_delete_inode and finish_pending_snaps to use
btrfs_join_transaction instead of btrfs_start_transaction to avoid deadlocks.
It would be better if btrfs_delete_inode didn't use the join, but the
call path that triggers it is:
btrfs_commit_transaction->create_pending_snapshots->
create_pending_snapshot->btrfs_lookup_dentry->
fixup_tree_root_location->btrfs_read_fs_root->
btrfs_read_fs_root_no_name->btrfs_orphan_cleanup->iput
This will be fixed in a later patch by moving the orphan cleanup to the
cleaner thread.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/inode.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 |
2 files changed, 2 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1b35ea63b6ce..c0ca9c3723c0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2886,7 +2886,7 @@ void btrfs_delete_inode(struct inode *inode) | |||
2886 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 2886 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
2887 | 2887 | ||
2888 | btrfs_i_size_write(inode, 0); | 2888 | btrfs_i_size_write(inode, 0); |
2889 | trans = btrfs_start_transaction(root, 1); | 2889 | trans = btrfs_join_transaction(root, 1); |
2890 | 2890 | ||
2891 | btrfs_set_trans_block_group(trans, inode); | 2891 | btrfs_set_trans_block_group(trans, inode); |
2892 | ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0); | 2892 | ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 56ab1f5ea11b..8a08f9443340 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -800,7 +800,7 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | |||
800 | 800 | ||
801 | parent_inode = pending->dentry->d_parent->d_inode; | 801 | parent_inode = pending->dentry->d_parent->d_inode; |
802 | parent_root = BTRFS_I(parent_inode)->root; | 802 | parent_root = BTRFS_I(parent_inode)->root; |
803 | trans = btrfs_start_transaction(parent_root, 1); | 803 | trans = btrfs_join_transaction(parent_root, 1); |
804 | 804 | ||
805 | /* | 805 | /* |
806 | * insert the directory item | 806 | * insert the directory item |