Skip to content

Commit 2dd7e7b

Browse files
naotakdave
authored andcommitted
btrfs: zoned: wait for extent buffer IOs before finishing a zone
Before sending REQ_OP_ZONE_FINISH to a zone, we need to ensure that ongoing IOs already finished. Or, we will see a "Zone Is Full" error for the IOs, as the ZONE_FINISH command makes the zone full. We ensure that with btrfs_wait_block_group_reservations() and btrfs_wait_ordered_roots() for a data block group. And, for a metadata block group, the comparison of alloc_offset vs meta_write_pointer mostly ensures IOs for the allocated region already sent. However, there still can be a little time frame where the IOs are sent but not yet completed. Introduce wait_eb_writebacks() to ensure such IOs are completed for a metadata block group. It walks the buffer_radix to find extent buffers in the block group and calls wait_on_extent_buffer_writeback() on them. Fixes: afba2bc ("btrfs: zoned: implement active zone tracking") CC: [email protected] # 5.19+ Signed-off-by: Naohiro Aota <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent a362bb8 commit 2dd7e7b

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

fs/btrfs/zoned.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,10 +1918,44 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
19181918
return ret;
19191919
}
19201920

1921+
static void wait_eb_writebacks(struct btrfs_block_group *block_group)
1922+
{
1923+
struct btrfs_fs_info *fs_info = block_group->fs_info;
1924+
const u64 end = block_group->start + block_group->length;
1925+
struct radix_tree_iter iter;
1926+
struct extent_buffer *eb;
1927+
void __rcu **slot;
1928+
1929+
rcu_read_lock();
1930+
radix_tree_for_each_slot(slot, &fs_info->buffer_radix, &iter,
1931+
block_group->start >> fs_info->sectorsize_bits) {
1932+
eb = radix_tree_deref_slot(slot);
1933+
if (!eb)
1934+
continue;
1935+
if (radix_tree_deref_retry(eb)) {
1936+
slot = radix_tree_iter_retry(&iter);
1937+
continue;
1938+
}
1939+
1940+
if (eb->start < block_group->start)
1941+
continue;
1942+
if (eb->start >= end)
1943+
break;
1944+
1945+
slot = radix_tree_iter_resume(slot, &iter);
1946+
rcu_read_unlock();
1947+
wait_on_extent_buffer_writeback(eb);
1948+
rcu_read_lock();
1949+
}
1950+
rcu_read_unlock();
1951+
}
1952+
19211953
static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_written)
19221954
{
19231955
struct btrfs_fs_info *fs_info = block_group->fs_info;
19241956
struct map_lookup *map;
1957+
const bool is_metadata = (block_group->flags &
1958+
(BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM));
19251959
int ret = 0;
19261960
int i;
19271961

@@ -1932,8 +1966,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
19321966
}
19331967

19341968
/* Check if we have unwritten allocated space */
1935-
if ((block_group->flags &
1936-
(BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM)) &&
1969+
if (is_metadata &&
19371970
block_group->start + block_group->alloc_offset > block_group->meta_write_pointer) {
19381971
spin_unlock(&block_group->lock);
19391972
return -EAGAIN;
@@ -1958,6 +1991,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
19581991
/* No need to wait for NOCOW writers. Zoned mode does not allow that */
19591992
btrfs_wait_ordered_roots(fs_info, U64_MAX, block_group->start,
19601993
block_group->length);
1994+
/* Wait for extent buffers to be written. */
1995+
if (is_metadata)
1996+
wait_eb_writebacks(block_group);
19611997

19621998
spin_lock(&block_group->lock);
19631999

0 commit comments

Comments
 (0)