Skip to content

Commit a85f05e

Browse files
naotakdave
authored andcommitted
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: Naohiro Aota <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent a12b0dc commit a85f05e

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

fs/btrfs/extent-tree.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,6 +3478,7 @@ struct find_free_extent_ctl {
34783478
/* Basic allocation info */
34793479
u64 ram_bytes;
34803480
u64 num_bytes;
3481+
u64 min_alloc_size;
34813482
u64 empty_size;
34823483
u64 flags;
34833484
int delalloc;
@@ -3946,18 +3947,30 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
39463947
ffe_ctl->have_caching_bg && !ffe_ctl->orig_have_caching_bg)
39473948
ffe_ctl->orig_have_caching_bg = true;
39483949

3949-
if (!ins->objectid && ffe_ctl->loop >= LOOP_CACHING_WAIT &&
3950-
ffe_ctl->have_caching_bg)
3951-
return 1;
3952-
3953-
if (!ins->objectid && ++(ffe_ctl->index) < BTRFS_NR_RAID_TYPES)
3954-
return 1;
3955-
39563950
if (ins->objectid) {
39573951
found_extent(ffe_ctl, ins);
39583952
return 0;
39593953
}
39603954

3955+
if (ffe_ctl->max_extent_size >= ffe_ctl->min_alloc_size &&
3956+
!btrfs_can_activate_zone(fs_info->fs_devices, ffe_ctl->index)) {
3957+
/*
3958+
* If we have enough free space left in an already active block
3959+
* group and we can't activate any other zone now, retry the
3960+
* active ones with a smaller allocation size. Returning early
3961+
* from here will tell btrfs_reserve_extent() to haven the
3962+
* size.
3963+
*/
3964+
return -ENOSPC;
3965+
}
3966+
3967+
if (ffe_ctl->loop >= LOOP_CACHING_WAIT && ffe_ctl->have_caching_bg)
3968+
return 1;
3969+
3970+
ffe_ctl->index++;
3971+
if (ffe_ctl->index < BTRFS_NR_RAID_TYPES)
3972+
return 1;
3973+
39613974
/*
39623975
* LOOP_CACHING_NOWAIT, search partially cached block groups, kicking
39633976
* caching kthreads as we move along
@@ -4432,6 +4445,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
44324445

44334446
ffe_ctl.ram_bytes = ram_bytes;
44344447
ffe_ctl.num_bytes = num_bytes;
4448+
ffe_ctl.min_alloc_size = min_alloc_size;
44354449
ffe_ctl.empty_size = empty_size;
44364450
ffe_ctl.flags = flags;
44374451
ffe_ctl.delalloc = delalloc;

fs/btrfs/zoned.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,3 +1873,34 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group)
18731873

18741874
return ret;
18751875
}
1876+
1877+
bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, int raid_index)
1878+
{
1879+
struct btrfs_device *device;
1880+
bool ret = false;
1881+
1882+
if (!btrfs_is_zoned(fs_devices->fs_info))
1883+
return true;
1884+
1885+
/* Non-single profiles are not supported yet */
1886+
if (raid_index != BTRFS_RAID_SINGLE)
1887+
return false;
1888+
1889+
/* Check if there is a device with active zones left */
1890+
mutex_lock(&fs_devices->device_list_mutex);
1891+
list_for_each_entry(device, &fs_devices->devices, dev_list) {
1892+
struct btrfs_zoned_device_info *zinfo = device->zone_info;
1893+
1894+
if (!device->bdev)
1895+
continue;
1896+
1897+
if (!zinfo->max_active_zones ||
1898+
atomic_read(&zinfo->active_zones_left)) {
1899+
ret = true;
1900+
break;
1901+
}
1902+
}
1903+
mutex_unlock(&fs_devices->device_list_mutex);
1904+
1905+
return ret;
1906+
}

fs/btrfs/zoned.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info,
7171
u64 logical, u64 length);
7272
bool btrfs_zone_activate(struct btrfs_block_group *block_group);
7373
int btrfs_zone_finish(struct btrfs_block_group *block_group);
74+
bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices,
75+
int raid_index);
7476
#else /* CONFIG_BLK_DEV_ZONED */
7577
static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
7678
struct blk_zone *zone)
@@ -216,6 +218,12 @@ static inline int btrfs_zone_finish(struct btrfs_block_group *block_group)
216218
return 0;
217219
}
218220

221+
static inline bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices,
222+
int raid_index)
223+
{
224+
return true;
225+
}
226+
219227
#endif
220228

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

0 commit comments

Comments
 (0)