Skip to content
Permalink
Browse files
btrfs: zoned: finish fully written block group
If we have written to the zone capacity, the device automatically
deactivates the zone. Sync up block group side (the active BG list and
zone_is_active flag) with it.

We need to do it both on data BGs and metadata BGs. On data side, we add a
hook to btrfs_finish_ordered_io(). On metadata side, we use
end_extent_buffer_writeback().

To reduce excess lookup of a block group, we mark the last extent buffer in
a block group with EXTENT_BUFFER_ZONE_FINISH flag. This cannot be done for
data (ordered_extent), because the address may change due to
REQ_OP_ZONE_APPEND.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
  • Loading branch information
naota authored and intel-lab-lkp committed Aug 11, 2021
1 parent 5a0f1cb commit ccecd271dc2436fe587af8d2083c3c96ab86e309
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 2 deletions.
@@ -4152,6 +4152,9 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)

static void end_extent_buffer_writeback(struct extent_buffer *eb)
{
if (test_bit(EXTENT_BUFFER_ZONE_FINISH, &eb->bflags))
btrfs_zone_finish_endio(eb->fs_info, eb->start, eb->len);

clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
smp_mb__after_atomic();
wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
@@ -4753,8 +4756,14 @@ static int submit_eb_page(struct page *page, struct writeback_control *wbc,
free_extent_buffer(eb);
return ret;
}
if (cache)
if (cache) {
/* Impiles write in zoned btrfs*/
btrfs_put_block_group(cache);
/* Mark the last eb in a block group */
if (cache->seq_zone &&
eb->start + eb->len == cache->zone_capacity)
set_bit(EXTENT_BUFFER_ZONE_FINISH, &eb->bflags);
}
ret = write_one_eb(eb, wbc, epd);
free_extent_buffer(eb);
if (ret < 0)
@@ -32,6 +32,7 @@ enum {
/* write IO error */
EXTENT_BUFFER_WRITE_ERR,
EXTENT_BUFFER_NO_CHECK,
EXTENT_BUFFER_ZONE_FINISH,
};

/* these are flags for __process_pages_contig */
@@ -3010,8 +3010,12 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
goto out;
}

if (ordered_extent->bdev)
/* Non-null bdev implies a write on a sequential zone */
if (ordered_extent->bdev) {
btrfs_rewrite_logical_zoned(ordered_extent);
btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
logical_len);
}

btrfs_free_io_failure_record(inode, start, end);

@@ -1897,3 +1897,61 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices,

return ret;
}

int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical,
u64 length)
{
struct btrfs_block_group *block_group;
struct map_lookup *map;
struct btrfs_device *device;
u64 physical;
int ret;

if (!btrfs_is_zoned(fs_info))
return 0;

block_group = btrfs_lookup_block_group(fs_info, logical);
ASSERT(block_group);

if (logical + length < block_group->start + block_group->zone_capacity) {
ret = 0;
goto out;
}

spin_lock(&block_group->lock);

if (!block_group->zone_is_active) {
spin_unlock(&block_group->lock);
ret = 0;
goto out;
}

block_group->zone_is_active = 0;
/* We should have consumed all the free space */
ASSERT(block_group->alloc_offset == block_group->zone_capacity);
ASSERT(block_group->free_space_ctl->free_space == 0);
btrfs_clear_treelog_bg(block_group);
spin_unlock(&block_group->lock);

map = block_group->physical_map;
device = map->stripes[0].dev;
physical = map->stripes[0].physical;

if (!device->zone_info->max_active_zones) {
ret = 0;
goto out;
}

btrfs_dev_clear_active_zone(device, physical);

spin_lock(&fs_info->zone_active_bgs_lock);
ASSERT(!list_empty(&block_group->active_bg_list));
list_del_init(&block_group->active_bg_list);
spin_unlock(&fs_info->zone_active_bgs_lock);

btrfs_put_block_group(block_group);

out:
btrfs_put_block_group(block_group);
return ret;
}
@@ -73,6 +73,8 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group);
int btrfs_zone_finish(struct btrfs_block_group *block_group);
bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices,
int raid_index);
int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical,
u64 length);
#else /* CONFIG_BLK_DEV_ZONED */
static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
struct blk_zone *zone)
@@ -224,6 +226,12 @@ static inline bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices,
return true;
}

static inline int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info,
u64 logical, u64 length)
{
return 0;
}

#endif

static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)

0 comments on commit ccecd27

Please sign in to comment.