mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 12:34:02 +02:00
btrfs: zoned: consolidate zone finish functions
btrfs_zone_finish() and btrfs_zone_finish_endio() have similar code. Introduce do_zone_finish() to factor out the common code. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
1bfd476754
commit
d70cbdda75
137
fs/btrfs/zoned.c
137
fs/btrfs/zoned.c
|
|
@ -1873,20 +1873,14 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_zone_finish(struct btrfs_block_group *block_group)
|
static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_written)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = block_group->fs_info;
|
struct btrfs_fs_info *fs_info = block_group->fs_info;
|
||||||
struct map_lookup *map;
|
struct map_lookup *map;
|
||||||
struct btrfs_device *device;
|
bool need_zone_finish;
|
||||||
u64 physical;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!btrfs_is_zoned(fs_info))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
map = block_group->physical_map;
|
|
||||||
|
|
||||||
spin_lock(&block_group->lock);
|
spin_lock(&block_group->lock);
|
||||||
if (!block_group->zone_is_active) {
|
if (!block_group->zone_is_active) {
|
||||||
spin_unlock(&block_group->lock);
|
spin_unlock(&block_group->lock);
|
||||||
|
|
@ -1900,35 +1894,51 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group)
|
||||||
spin_unlock(&block_group->lock);
|
spin_unlock(&block_group->lock);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
spin_unlock(&block_group->lock);
|
|
||||||
|
|
||||||
ret = btrfs_inc_block_group_ro(block_group, false);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* Ensure all writes in this block group finish */
|
|
||||||
btrfs_wait_block_group_reservations(block_group);
|
|
||||||
/* No need to wait for NOCOW writers. Zoned mode does not allow that. */
|
|
||||||
btrfs_wait_ordered_roots(fs_info, U64_MAX, block_group->start,
|
|
||||||
block_group->length);
|
|
||||||
|
|
||||||
spin_lock(&block_group->lock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bail out if someone already deactivated the block group, or
|
* If we are sure that the block group is full (= no more room left for
|
||||||
* allocated space is left in the block group.
|
* new allocation) and the IO for the last usable block is completed, we
|
||||||
|
* don't need to wait for the other IOs. This holds because we ensure
|
||||||
|
* the sequential IO submissions using the ZONE_APPEND command for data
|
||||||
|
* and block_group->meta_write_pointer for metadata.
|
||||||
*/
|
*/
|
||||||
if (!block_group->zone_is_active) {
|
if (!fully_written) {
|
||||||
spin_unlock(&block_group->lock);
|
spin_unlock(&block_group->lock);
|
||||||
btrfs_dec_block_group_ro(block_group);
|
|
||||||
return 0;
|
ret = btrfs_inc_block_group_ro(block_group, false);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Ensure all writes in this block group finish */
|
||||||
|
btrfs_wait_block_group_reservations(block_group);
|
||||||
|
/* No need to wait for NOCOW writers. Zoned mode does not allow that */
|
||||||
|
btrfs_wait_ordered_roots(fs_info, U64_MAX, block_group->start,
|
||||||
|
block_group->length);
|
||||||
|
|
||||||
|
spin_lock(&block_group->lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bail out if someone already deactivated the block group, or
|
||||||
|
* allocated space is left in the block group.
|
||||||
|
*/
|
||||||
|
if (!block_group->zone_is_active) {
|
||||||
|
spin_unlock(&block_group->lock);
|
||||||
|
btrfs_dec_block_group_ro(block_group);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block_group->reserved) {
|
||||||
|
spin_unlock(&block_group->lock);
|
||||||
|
btrfs_dec_block_group_ro(block_group);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_group->reserved) {
|
/*
|
||||||
spin_unlock(&block_group->lock);
|
* The block group is not fully allocated, so not fully written yet. We
|
||||||
btrfs_dec_block_group_ro(block_group);
|
* need to send ZONE_FINISH command to free up an active zone.
|
||||||
return -EAGAIN;
|
*/
|
||||||
}
|
need_zone_finish = !btrfs_zoned_bg_is_full(block_group);
|
||||||
|
|
||||||
block_group->zone_is_active = 0;
|
block_group->zone_is_active = 0;
|
||||||
block_group->alloc_offset = block_group->zone_capacity;
|
block_group->alloc_offset = block_group->zone_capacity;
|
||||||
|
|
@ -1937,24 +1947,29 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group)
|
||||||
btrfs_clear_data_reloc_bg(block_group);
|
btrfs_clear_data_reloc_bg(block_group);
|
||||||
spin_unlock(&block_group->lock);
|
spin_unlock(&block_group->lock);
|
||||||
|
|
||||||
|
map = block_group->physical_map;
|
||||||
for (i = 0; i < map->num_stripes; i++) {
|
for (i = 0; i < map->num_stripes; i++) {
|
||||||
device = map->stripes[i].dev;
|
struct btrfs_device *device = map->stripes[i].dev;
|
||||||
physical = map->stripes[i].physical;
|
const u64 physical = map->stripes[i].physical;
|
||||||
|
|
||||||
if (device->zone_info->max_active_zones == 0)
|
if (device->zone_info->max_active_zones == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH,
|
if (need_zone_finish) {
|
||||||
physical >> SECTOR_SHIFT,
|
ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH,
|
||||||
device->zone_info->zone_size >> SECTOR_SHIFT,
|
physical >> SECTOR_SHIFT,
|
||||||
GFP_NOFS);
|
device->zone_info->zone_size >> SECTOR_SHIFT,
|
||||||
|
GFP_NOFS);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
btrfs_dev_clear_active_zone(device, physical);
|
btrfs_dev_clear_active_zone(device, physical);
|
||||||
}
|
}
|
||||||
btrfs_dec_block_group_ro(block_group);
|
|
||||||
|
if (!fully_written)
|
||||||
|
btrfs_dec_block_group_ro(block_group);
|
||||||
|
|
||||||
spin_lock(&fs_info->zone_active_bgs_lock);
|
spin_lock(&fs_info->zone_active_bgs_lock);
|
||||||
ASSERT(!list_empty(&block_group->active_bg_list));
|
ASSERT(!list_empty(&block_group->active_bg_list));
|
||||||
|
|
@ -1967,6 +1982,14 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btrfs_zone_finish(struct btrfs_block_group *block_group)
|
||||||
|
{
|
||||||
|
if (!btrfs_is_zoned(block_group->fs_info))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return do_zone_finish(block_group, false);
|
||||||
|
}
|
||||||
|
|
||||||
bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
|
bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = fs_devices->fs_info;
|
struct btrfs_fs_info *fs_info = fs_devices->fs_info;
|
||||||
|
|
@ -1998,9 +2021,6 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
|
||||||
void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 length)
|
void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 length)
|
||||||
{
|
{
|
||||||
struct btrfs_block_group *block_group;
|
struct btrfs_block_group *block_group;
|
||||||
struct map_lookup *map;
|
|
||||||
struct btrfs_device *device;
|
|
||||||
u64 physical;
|
|
||||||
|
|
||||||
if (!btrfs_is_zoned(fs_info))
|
if (!btrfs_is_zoned(fs_info))
|
||||||
return;
|
return;
|
||||||
|
|
@ -2011,36 +2031,7 @@ void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 len
|
||||||
if (logical + length < block_group->start + block_group->zone_capacity)
|
if (logical + length < block_group->start + block_group->zone_capacity)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock(&block_group->lock);
|
do_zone_finish(block_group, true);
|
||||||
|
|
||||||
if (!block_group->zone_is_active) {
|
|
||||||
spin_unlock(&block_group->lock);
|
|
||||||
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);
|
|
||||||
btrfs_clear_data_reloc_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)
|
|
||||||
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:
|
out:
|
||||||
btrfs_put_block_group(block_group);
|
btrfs_put_block_group(block_group);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user