Commit a85f05e5 authored by Naohiro Aota's avatar Naohiro Aota Committed by David Sterba

btrfs: zoned: avoid chunk allocation if active block group has enough space

The current extent allocator tries to allocate a new block group when the
existing block groups do not have enough space. On a ZNS device, a new
block group means a new active zone. If the number of active zones has
already reached the max_active_zones, activating a new zone needs to finish
an existing zone, leading to wasting the free space there.

So, instead, it should reuse the existing active block groups as much as
possible when we can't activate any other zones without sacrificing an
already activated block group.

While at it, I converted find_free_extent_update_loop() to check the
found_extent() case early and made the other conditions simpler.
Signed-off-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent a12b0dc0
...@@ -3478,6 +3478,7 @@ struct find_free_extent_ctl { ...@@ -3478,6 +3478,7 @@ struct find_free_extent_ctl {
/* Basic allocation info */ /* Basic allocation info */
u64 ram_bytes; u64 ram_bytes;
u64 num_bytes; u64 num_bytes;
u64 min_alloc_size;
u64 empty_size; u64 empty_size;
u64 flags; u64 flags;
int delalloc; int delalloc;
...@@ -3946,18 +3947,30 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info, ...@@ -3946,18 +3947,30 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
ffe_ctl->have_caching_bg && !ffe_ctl->orig_have_caching_bg) ffe_ctl->have_caching_bg && !ffe_ctl->orig_have_caching_bg)
ffe_ctl->orig_have_caching_bg = true; ffe_ctl->orig_have_caching_bg = true;
if (!ins->objectid && ffe_ctl->loop >= LOOP_CACHING_WAIT &&
ffe_ctl->have_caching_bg)
return 1;
if (!ins->objectid && ++(ffe_ctl->index) < BTRFS_NR_RAID_TYPES)
return 1;
if (ins->objectid) { if (ins->objectid) {
found_extent(ffe_ctl, ins); found_extent(ffe_ctl, ins);
return 0; return 0;
} }
if (ffe_ctl->max_extent_size >= ffe_ctl->min_alloc_size &&
!btrfs_can_activate_zone(fs_info->fs_devices, ffe_ctl->index)) {
/*
* If we have enough free space left in an already active block
* group and we can't activate any other zone now, retry the
* active ones with a smaller allocation size. Returning early
* from here will tell btrfs_reserve_extent() to haven the
* size.
*/
return -ENOSPC;
}
if (ffe_ctl->loop >= LOOP_CACHING_WAIT && ffe_ctl->have_caching_bg)
return 1;
ffe_ctl->index++;
if (ffe_ctl->index < BTRFS_NR_RAID_TYPES)
return 1;
/* /*
* LOOP_CACHING_NOWAIT, search partially cached block groups, kicking * LOOP_CACHING_NOWAIT, search partially cached block groups, kicking
* caching kthreads as we move along * caching kthreads as we move along
...@@ -4432,6 +4445,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, ...@@ -4432,6 +4445,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
ffe_ctl.ram_bytes = ram_bytes; ffe_ctl.ram_bytes = ram_bytes;
ffe_ctl.num_bytes = num_bytes; ffe_ctl.num_bytes = num_bytes;
ffe_ctl.min_alloc_size = min_alloc_size;
ffe_ctl.empty_size = empty_size; ffe_ctl.empty_size = empty_size;
ffe_ctl.flags = flags; ffe_ctl.flags = flags;
ffe_ctl.delalloc = delalloc; ffe_ctl.delalloc = delalloc;
......
...@@ -1873,3 +1873,34 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group) ...@@ -1873,3 +1873,34 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group)
return ret; return ret;
} }
bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, int raid_index)
{
struct btrfs_device *device;
bool ret = false;
if (!btrfs_is_zoned(fs_devices->fs_info))
return true;
/* Non-single profiles are not supported yet */
if (raid_index != BTRFS_RAID_SINGLE)
return false;
/* Check if there is a device with active zones left */
mutex_lock(&fs_devices->device_list_mutex);
list_for_each_entry(device, &fs_devices->devices, dev_list) {
struct btrfs_zoned_device_info *zinfo = device->zone_info;
if (!device->bdev)
continue;
if (!zinfo->max_active_zones ||
atomic_read(&zinfo->active_zones_left)) {
ret = true;
break;
}
}
mutex_unlock(&fs_devices->device_list_mutex);
return ret;
}
...@@ -71,6 +71,8 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info, ...@@ -71,6 +71,8 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info,
u64 logical, u64 length); u64 logical, u64 length);
bool btrfs_zone_activate(struct btrfs_block_group *block_group); bool btrfs_zone_activate(struct btrfs_block_group *block_group);
int btrfs_zone_finish(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);
#else /* CONFIG_BLK_DEV_ZONED */ #else /* CONFIG_BLK_DEV_ZONED */
static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
struct blk_zone *zone) struct blk_zone *zone)
...@@ -216,6 +218,12 @@ static inline int btrfs_zone_finish(struct btrfs_block_group *block_group) ...@@ -216,6 +218,12 @@ static inline int btrfs_zone_finish(struct btrfs_block_group *block_group)
return 0; return 0;
} }
static inline bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices,
int raid_index)
{
return true;
}
#endif #endif
static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos) static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
......
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