Commit 18f62b86 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David Sterba
Browse files

btrfs: cleanup the COW fallback logic in run_delalloc_nocow



Use the block group pointer used to track the outstanding NOCOW writes as
a boolean to remove the duplicate nocow variable, and keep it contained
in the main loop to simplify the logic.

Reviewed-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 953fa5ce
Loading
Loading
Loading
Loading
+22 −25
Original line number Diff line number Diff line
@@ -1974,8 +1974,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
	int ret;
	bool check_prev = true;
	u64 ino = btrfs_ino(inode);
	struct btrfs_block_group *bg;
	bool nocow = false;
	struct can_nocow_file_extent_args nocow_args = { 0 };

	path = btrfs_alloc_path();
@@ -1993,6 +1991,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
	nocow_args.writeback_path = true;

	while (1) {
		struct btrfs_block_group *nocow_bg = NULL;
		struct btrfs_ordered_extent *ordered;
		struct btrfs_key found_key;
		struct btrfs_file_extent_item *fi;
@@ -2003,8 +2002,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
		int extent_type;
		bool is_prealloc;

		nocow = false;

		ret = btrfs_lookup_file_extent(NULL, root, path, ino,
					       cur_offset, 0);
		if (ret < 0)
@@ -2063,7 +2060,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
		if (found_key.offset > cur_offset) {
			extent_end = found_key.offset;
			extent_type = 0;
			goto out_check;
			goto must_cow;
		}

		/*
@@ -2096,18 +2093,19 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
		if (ret < 0)
			goto error;
		if (ret == 0)
			goto out_check;
			goto must_cow;

		ret = 0;
		bg = btrfs_inc_nocow_writers(fs_info, nocow_args.disk_bytenr);
		if (bg)
			nocow = true;
out_check:
		nocow_bg = btrfs_inc_nocow_writers(fs_info, nocow_args.disk_bytenr);
		if (!nocow_bg) {
must_cow:
			/*
		 * If nocow is false then record the beginning of the range
		 * that needs to be COWed
			 * If we can't perform NOCOW writeback for the range,
			 * then record the beginning of the range that needs to
			 * be COWed.  It will be written out before the next
			 * NOCOW range if we find one, or when exiting this
			 * loop.
			 */
		if (!nocow) {
			if (cow_start == (u64)-1)
				cow_start = cur_offset;
			cur_offset = extent_end;
@@ -2128,9 +2126,11 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
			ret = fallback_to_cow(inode, locked_page,
					      cow_start, found_key.offset - 1);
			cow_start = (u64)-1;
			if (ret)
			if (ret) {
				btrfs_dec_nocow_writers(nocow_bg);
				goto error;
			}
		}

		nocow_end = cur_offset + nocow_args.num_bytes - 1;
		is_prealloc = extent_type == BTRFS_FILE_EXTENT_PREALLOC;
@@ -2146,6 +2146,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
					  ram_bytes, BTRFS_COMPRESS_NONE,
					  BTRFS_ORDERED_PREALLOC);
			if (IS_ERR(em)) {
				btrfs_dec_nocow_writers(nocow_bg);
				ret = PTR_ERR(em);
				goto error;
			}
@@ -2159,6 +2160,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
				? (1 << BTRFS_ORDERED_PREALLOC)
				: (1 << BTRFS_ORDERED_NOCOW),
				BTRFS_COMPRESS_NONE);
		btrfs_dec_nocow_writers(nocow_bg);
		if (IS_ERR(ordered)) {
			if (is_prealloc) {
				btrfs_drop_extent_map_range(inode, cur_offset,
@@ -2168,11 +2170,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
			goto error;
		}

		if (nocow) {
			btrfs_dec_nocow_writers(bg);
			nocow = false;
		}

		if (btrfs_is_data_reloc_root(root))
			/*
			 * Error handled later, as we must prevent
@@ -2213,10 +2210,10 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
			goto error;
	}

error:
	if (nocow)
		btrfs_dec_nocow_writers(bg);
	btrfs_free_path(path);
	return 0;

error:
	/*
	 * If an error happened while a COW region is outstanding, cur_offset
	 * needs to be reset to cow_start to ensure the COW region is unlocked
@@ -2224,7 +2221,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
	 */
	if (cow_start != (u64)-1)
		cur_offset = cow_start;
	if (ret && cur_offset < end)
	if (cur_offset < end)
		extent_clear_unlock_delalloc(inode, cur_offset, end,
					     locked_page, EXTENT_LOCKED |
					     EXTENT_DELALLOC | EXTENT_DEFRAG |