Btrfs: Use btrfs_join_transaction to avoid deadlocks during snapshot creation
authorYan Zheng <zheng.yan@oracle.com>
Tue, 6 Jan 2009 14:58:06 +0000 (09:58 -0500)
committerChris Mason <chris.mason@oracle.com>
Tue, 6 Jan 2009 14:58:06 +0000 (09:58 -0500)
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>
fs/btrfs/inode.c
fs/btrfs/transaction.c

index 1b35ea63b6cec6dc4236af8c9c9ba1bfb6eb8004..c0ca9c3723c0661823b4c0f6b7c018c66dcfd369 100644 (file)
@@ -2886,7 +2886,7 @@ void btrfs_delete_inode(struct inode *inode)
        btrfs_wait_ordered_range(inode, 0, (u64)-1);
 
        btrfs_i_size_write(inode, 0);
-       trans = btrfs_start_transaction(root, 1);
+       trans = btrfs_join_transaction(root, 1);
 
        btrfs_set_trans_block_group(trans, inode);
        ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0);
index 56ab1f5ea11bb0cb2917de61fc238548b81d94e6..8a08f94433407e6c8ca7ce2e15285ef75115bb26 100644 (file)
@@ -800,7 +800,7 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
 
        parent_inode = pending->dentry->d_parent->d_inode;
        parent_root = BTRFS_I(parent_inode)->root;
-       trans = btrfs_start_transaction(parent_root, 1);
+       trans = btrfs_join_transaction(parent_root, 1);
 
        /*
         * insert the directory item