Skip to content

Commit b093151

Browse files
naotakdave
authored andcommitted
btrfs: zoned: activate metadata block group on flush_space
For metadata space on zoned filesystem, reaching ALLOC_CHUNK{,_FORCE} means we don't have enough space left in the active_total_bytes. Before allocating a new chunk, we can try to activate an existing block group in this case. Also, allocating a chunk is not enough to grant a ticket for metadata space on zoned filesystem we need to activate the block group to increase the active_total_bytes. btrfs_zoned_activate_one_bg() implements the activation feature. It will activate a block group by (maybe) finishing a block group. It will give up activating a block group if it cannot finish any block group. CC: stable@vger.kernel.org # 5.16+ Fixes: afba2bc ("btrfs: zoned: implement active zone tracking") Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 79417d0 commit b093151

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

fs/btrfs/space-info.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "ordered-data.h"
1010
#include "transaction.h"
1111
#include "block-group.h"
12+
#include "zoned.h"
1213

1314
/*
1415
* HOW DOES SPACE RESERVATION WORK
@@ -724,6 +725,18 @@ static void flush_space(struct btrfs_fs_info *fs_info,
724725
break;
725726
case ALLOC_CHUNK:
726727
case ALLOC_CHUNK_FORCE:
728+
/*
729+
* For metadata space on zoned filesystem, reaching here means we
730+
* don't have enough space left in active_total_bytes. Try to
731+
* activate a block group first, because we may have inactive
732+
* block group already allocated.
733+
*/
734+
ret = btrfs_zoned_activate_one_bg(fs_info, space_info, false);
735+
if (ret < 0)
736+
break;
737+
else if (ret == 1)
738+
break;
739+
727740
trans = btrfs_join_transaction(root);
728741
if (IS_ERR(trans)) {
729742
ret = PTR_ERR(trans);
@@ -734,6 +747,23 @@ static void flush_space(struct btrfs_fs_info *fs_info,
734747
(state == ALLOC_CHUNK) ? CHUNK_ALLOC_NO_FORCE :
735748
CHUNK_ALLOC_FORCE);
736749
btrfs_end_transaction(trans);
750+
751+
/*
752+
* For metadata space on zoned filesystem, allocating a new chunk
753+
* is not enough. We still need to activate the block * group.
754+
* Active the newly allocated block group by (maybe) finishing
755+
* a block group.
756+
*/
757+
if (ret == 1) {
758+
ret = btrfs_zoned_activate_one_bg(fs_info, space_info, true);
759+
/*
760+
* Revert to the original ret regardless we could finish
761+
* one block group or not.
762+
*/
763+
if (ret >= 0)
764+
ret = 1;
765+
}
766+
737767
if (ret > 0 || ret == -ENOSPC)
738768
ret = 0;
739769
break;

fs/btrfs/zoned.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,3 +2226,56 @@ int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
22262226

22272227
return ret < 0 ? ret : 1;
22282228
}
2229+
2230+
int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
2231+
struct btrfs_space_info *space_info,
2232+
bool do_finish)
2233+
{
2234+
struct btrfs_block_group *bg;
2235+
int index;
2236+
2237+
if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
2238+
return 0;
2239+
2240+
/* No more block groups to activate */
2241+
if (space_info->active_total_bytes == space_info->total_bytes)
2242+
return 0;
2243+
2244+
for (;;) {
2245+
int ret;
2246+
bool need_finish = false;
2247+
2248+
down_read(&space_info->groups_sem);
2249+
for (index = 0; index < BTRFS_NR_RAID_TYPES; index++) {
2250+
list_for_each_entry(bg, &space_info->block_groups[index],
2251+
list) {
2252+
if (!spin_trylock(&bg->lock))
2253+
continue;
2254+
if (btrfs_zoned_bg_is_full(bg) || bg->zone_is_active) {
2255+
spin_unlock(&bg->lock);
2256+
continue;
2257+
}
2258+
spin_unlock(&bg->lock);
2259+
2260+
if (btrfs_zone_activate(bg)) {
2261+
up_read(&space_info->groups_sem);
2262+
return 1;
2263+
}
2264+
2265+
need_finish = true;
2266+
}
2267+
}
2268+
up_read(&space_info->groups_sem);
2269+
2270+
if (!do_finish || !need_finish)
2271+
break;
2272+
2273+
ret = btrfs_zone_finish_one_bg(fs_info);
2274+
if (ret == 0)
2275+
break;
2276+
if (ret < 0)
2277+
return ret;
2278+
}
2279+
2280+
return 0;
2281+
}

fs/btrfs/zoned.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ bool btrfs_zoned_should_reclaim(struct btrfs_fs_info *fs_info);
8181
void btrfs_zoned_release_data_reloc_bg(struct btrfs_fs_info *fs_info, u64 logical,
8282
u64 length);
8383
int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info);
84+
int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
85+
struct btrfs_space_info *space_info, bool do_finish);
8486
#else /* CONFIG_BLK_DEV_ZONED */
8587
static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
8688
struct blk_zone *zone)
@@ -256,6 +258,14 @@ static inline int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
256258
return 1;
257259
}
258260

261+
static inline int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
262+
struct btrfs_space_info *space_info,
263+
bool do_finish)
264+
{
265+
/* Consider all the block groups are active */
266+
return 0;
267+
}
268+
259269
#endif
260270

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

0 commit comments

Comments
 (0)