Commit 8d510121 authored by Nikolay Borisov's avatar Nikolay Borisov Committed by David Sterba
Browse files

btrfs: Rename btrfs_join_transaction_nolock



This function is used only during the final phase of freespace cache
writeout. This is necessary since using the plain btrfs_join_transaction
api is deadlock prone. The deadlock looks like:

T1:
btrfs_commit_transaction
  commit_cowonly_roots
    btrfs_write_dirty_block_groups
      btrfs_wait_cache_io
        __btrfs_wait_cache_io
       btrfs_wait_ordered_range <-- Triggers ordered IO for freespace
                                    inode and blocks transaction commit
				    until freespace cache writeout

T2: <-- after T1 has triggered the writeout
finish_ordered_fn
  btrfs_finish_ordered_io
    btrfs_join_transaction <--- this would block waiting for current
                                transaction to commit, but since trans
				commit is waiting for this writeout to
				finish

The special purpose functions prevents it by simply skipping the "wait
for writeout" since it's guaranteed the transaction won't proceed until
we are done.

Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ce6d3eb6
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -3066,7 +3066,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
	int compress_type = 0;
	int ret = 0;
	u64 logical_len = ordered_extent->len;
	bool nolock;
	bool freespace_inode;
	bool truncated = false;
	bool range_locked = false;
	bool clear_new_delalloc_bytes = false;
@@ -3077,7 +3077,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
	    !test_bit(BTRFS_ORDERED_DIRECT, &ordered_extent->flags))
		clear_new_delalloc_bytes = true;

	nolock = btrfs_is_free_space_inode(BTRFS_I(inode));
	freespace_inode = btrfs_is_free_space_inode(BTRFS_I(inode));

	if (test_bit(BTRFS_ORDERED_IOERR, &ordered_extent->flags)) {
		ret = -EIO;
@@ -3108,8 +3108,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
		btrfs_qgroup_free_data(inode, NULL, ordered_extent->file_offset,
				       ordered_extent->len);
		btrfs_ordered_update_i_size(inode, 0, ordered_extent);
		if (nolock)
			trans = btrfs_join_transaction_nolock(root);
		if (freespace_inode)
			trans = btrfs_join_transaction_spacecache(root);
		else
			trans = btrfs_join_transaction(root);
		if (IS_ERR(trans)) {
@@ -3143,8 +3143,8 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
			EXTENT_DEFRAG, 0, 0, &cached_state);
	}

	if (nolock)
		trans = btrfs_join_transaction_nolock(root);
	if (freespace_inode)
		trans = btrfs_join_transaction_spacecache(root);
	else
		trans = btrfs_join_transaction(root);
	if (IS_ERR(trans)) {
+1 −1
Original line number Diff line number Diff line
@@ -729,7 +729,7 @@ struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)
				 true);
}

struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root)
struct btrfs_trans_handle *btrfs_join_transaction_spacecache(struct btrfs_root *root)
{
	return start_transaction(root, 0, TRANS_JOIN_NOLOCK,
				 BTRFS_RESERVE_NO_FLUSH, true);
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
					unsigned int num_items,
					int min_factor);
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_join_transaction_spacecache(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_join_transaction_nostart(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root);
struct btrfs_trans_handle *btrfs_attach_transaction_barrier(