aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorNaohiro Aota <naohiro.aota@wdc.com>2022-07-09 08:18:49 +0900
committerDavid Sterba <dsterba@suse.com>2022-07-25 17:45:42 +0200
commit898793d992c23dac6126a6a94ad893eae1a2c9df (patch)
treebbeb65d59bd88f4f0b605e175994f23af68e808c /fs/btrfs/extent-tree.c
parentbtrfs: zoned: activate necessary block group (diff)
downloadwireguard-linux-898793d992c23dac6126a6a94ad893eae1a2c9df.tar.xz
wireguard-linux-898793d992c23dac6126a6a94ad893eae1a2c9df.zip
btrfs: zoned: write out partially allocated region
cow_file_range() works in an all-or-nothing way: if it fails to allocate an extent for a part of the given region, it gives up all the region including the successfully allocated parts. On cow_file_range(), run_delalloc_zoned() writes data for the region only when it successfully allocate all the region. This all-or-nothing allocation and write-out are problematic when available space in all the block groups are get tight with the active zone restriction. btrfs_reserve_extent() try hard to utilize the left space in the active block groups and gives up finally and fails with -ENOSPC. However, if we send IOs for the successfully allocated region, we can finish a zone and can continue on the rest of the allocation on a newly allocated block group. This patch implements the partial write-out for run_delalloc_zoned(). With this patch applied, cow_file_range() returns -EAGAIN to tell the caller to do something to progress the further allocation, and tells the successfully allocated region with done_offset. Furthermore, the zoned extent allocator returns -EAGAIN to tell cow_file_range() going back to the caller side. Actually, we still need to wait for an IO to complete to continue the allocation. The next patch implements that part. CC: stable@vger.kernel.org # 5.16+ Fixes: afba2bc036b0 ("btrfs: zoned: implement active zone tracking") Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 5b604c3dc357..ea3ec1e761e8 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3997,6 +3997,16 @@ static int can_allocate_chunk_zoned(struct btrfs_fs_info *fs_info,
return -ENOSPC;
/*
+ * Even min_alloc_size is not left in any block groups. Since we cannot
+ * activate a new block group, allocating it may not help. Let's tell a
+ * caller to try again and hope it progress something by writing some
+ * parts of the region. That is only possible for data block groups,
+ * where a part of the region can be written.
+ */
+ if (ffe_ctl->flags & BTRFS_BLOCK_GROUP_DATA)
+ return -EAGAIN;
+
+ /*
* We cannot activate a new block group and no enough space left in any
* block groups. So, allocating a new block group may not help. But,
* there is nothing to do anyway, so let's go with it.