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

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
...@@ -1974,8 +1974,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -1974,8 +1974,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
int ret; int ret;
bool check_prev = true; bool check_prev = true;
u64 ino = btrfs_ino(inode); u64 ino = btrfs_ino(inode);
struct btrfs_block_group *bg;
bool nocow = false;
struct can_nocow_file_extent_args nocow_args = { 0 }; struct can_nocow_file_extent_args nocow_args = { 0 };
path = btrfs_alloc_path(); path = btrfs_alloc_path();
...@@ -1993,6 +1991,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -1993,6 +1991,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
nocow_args.writeback_path = true; nocow_args.writeback_path = true;
while (1) { while (1) {
struct btrfs_block_group *nocow_bg = NULL;
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_file_extent_item *fi; struct btrfs_file_extent_item *fi;
...@@ -2003,8 +2002,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2003,8 +2002,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
int extent_type; int extent_type;
bool is_prealloc; bool is_prealloc;
nocow = false;
ret = btrfs_lookup_file_extent(NULL, root, path, ino, ret = btrfs_lookup_file_extent(NULL, root, path, ino,
cur_offset, 0); cur_offset, 0);
if (ret < 0) if (ret < 0)
...@@ -2063,7 +2060,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2063,7 +2060,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
if (found_key.offset > cur_offset) { if (found_key.offset > cur_offset) {
extent_end = found_key.offset; extent_end = found_key.offset;
extent_type = 0; extent_type = 0;
goto out_check; goto must_cow;
} }
/* /*
...@@ -2096,18 +2093,19 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2096,18 +2093,19 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
if (ret < 0) if (ret < 0)
goto error; goto error;
if (ret == 0) if (ret == 0)
goto out_check; goto must_cow;
ret = 0; ret = 0;
bg = btrfs_inc_nocow_writers(fs_info, nocow_args.disk_bytenr); nocow_bg = btrfs_inc_nocow_writers(fs_info, nocow_args.disk_bytenr);
if (bg) if (!nocow_bg) {
nocow = true; must_cow:
out_check: /*
/* * If we can't perform NOCOW writeback for the range,
* If nocow is false then record the beginning of the range * then record the beginning of the range that needs to
* that needs to be COWed * be COWed. It will be written out before the next
*/ * NOCOW range if we find one, or when exiting this
if (!nocow) { * loop.
*/
if (cow_start == (u64)-1) if (cow_start == (u64)-1)
cow_start = cur_offset; cow_start = cur_offset;
cur_offset = extent_end; cur_offset = extent_end;
...@@ -2128,8 +2126,10 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2128,8 +2126,10 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
ret = fallback_to_cow(inode, locked_page, ret = fallback_to_cow(inode, locked_page,
cow_start, found_key.offset - 1); cow_start, found_key.offset - 1);
cow_start = (u64)-1; cow_start = (u64)-1;
if (ret) if (ret) {
btrfs_dec_nocow_writers(nocow_bg);
goto error; goto error;
}
} }
nocow_end = cur_offset + nocow_args.num_bytes - 1; nocow_end = cur_offset + nocow_args.num_bytes - 1;
...@@ -2146,6 +2146,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2146,6 +2146,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
ram_bytes, BTRFS_COMPRESS_NONE, ram_bytes, BTRFS_COMPRESS_NONE,
BTRFS_ORDERED_PREALLOC); BTRFS_ORDERED_PREALLOC);
if (IS_ERR(em)) { if (IS_ERR(em)) {
btrfs_dec_nocow_writers(nocow_bg);
ret = PTR_ERR(em); ret = PTR_ERR(em);
goto error; goto error;
} }
...@@ -2159,6 +2160,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2159,6 +2160,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
? (1 << BTRFS_ORDERED_PREALLOC) ? (1 << BTRFS_ORDERED_PREALLOC)
: (1 << BTRFS_ORDERED_NOCOW), : (1 << BTRFS_ORDERED_NOCOW),
BTRFS_COMPRESS_NONE); BTRFS_COMPRESS_NONE);
btrfs_dec_nocow_writers(nocow_bg);
if (IS_ERR(ordered)) { if (IS_ERR(ordered)) {
if (is_prealloc) { if (is_prealloc) {
btrfs_drop_extent_map_range(inode, cur_offset, btrfs_drop_extent_map_range(inode, cur_offset,
...@@ -2168,11 +2170,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2168,11 +2170,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
goto error; goto error;
} }
if (nocow) {
btrfs_dec_nocow_writers(bg);
nocow = false;
}
if (btrfs_is_data_reloc_root(root)) if (btrfs_is_data_reloc_root(root))
/* /*
* Error handled later, as we must prevent * Error handled later, as we must prevent
...@@ -2213,10 +2210,10 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ...@@ -2213,10 +2210,10 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
goto error; goto error;
} }
error: btrfs_free_path(path);
if (nocow) return 0;
btrfs_dec_nocow_writers(bg);
error:
/* /*
* If an error happened while a COW region is outstanding, cur_offset * 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 * 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, ...@@ -2224,7 +2221,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
*/ */
if (cow_start != (u64)-1) if (cow_start != (u64)-1)
cur_offset = cow_start; cur_offset = cow_start;
if (ret && cur_offset < end) if (cur_offset < end)
extent_clear_unlock_delalloc(inode, cur_offset, end, extent_clear_unlock_delalloc(inode, cur_offset, end,
locked_page, EXTENT_LOCKED | locked_page, EXTENT_LOCKED |
EXTENT_DELALLOC | EXTENT_DEFRAG | EXTENT_DELALLOC | EXTENT_DEFRAG |
......
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