mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
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: afba2bc036
("btrfs: zoned: implement active zone tracking")
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
79417d040f
commit
b093151391
@ -9,6 +9,7 @@
|
||||
#include "ordered-data.h"
|
||||
#include "transaction.h"
|
||||
#include "block-group.h"
|
||||
#include "zoned.h"
|
||||
|
||||
/*
|
||||
* HOW DOES SPACE RESERVATION WORK
|
||||
@ -724,6 +725,18 @@ static void flush_space(struct btrfs_fs_info *fs_info,
|
||||
break;
|
||||
case ALLOC_CHUNK:
|
||||
case ALLOC_CHUNK_FORCE:
|
||||
/*
|
||||
* For metadata space on zoned filesystem, reaching here means we
|
||||
* don't have enough space left in active_total_bytes. Try to
|
||||
* activate a block group first, because we may have inactive
|
||||
* block group already allocated.
|
||||
*/
|
||||
ret = btrfs_zoned_activate_one_bg(fs_info, space_info, false);
|
||||
if (ret < 0)
|
||||
break;
|
||||
else if (ret == 1)
|
||||
break;
|
||||
|
||||
trans = btrfs_join_transaction(root);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
@ -734,6 +747,23 @@ static void flush_space(struct btrfs_fs_info *fs_info,
|
||||
(state == ALLOC_CHUNK) ? CHUNK_ALLOC_NO_FORCE :
|
||||
CHUNK_ALLOC_FORCE);
|
||||
btrfs_end_transaction(trans);
|
||||
|
||||
/*
|
||||
* For metadata space on zoned filesystem, allocating a new chunk
|
||||
* is not enough. We still need to activate the block * group.
|
||||
* Active the newly allocated block group by (maybe) finishing
|
||||
* a block group.
|
||||
*/
|
||||
if (ret == 1) {
|
||||
ret = btrfs_zoned_activate_one_bg(fs_info, space_info, true);
|
||||
/*
|
||||
* Revert to the original ret regardless we could finish
|
||||
* one block group or not.
|
||||
*/
|
||||
if (ret >= 0)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret > 0 || ret == -ENOSPC)
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -2226,3 +2226,56 @@ int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
|
||||
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
|
||||
int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_space_info *space_info,
|
||||
bool do_finish)
|
||||
{
|
||||
struct btrfs_block_group *bg;
|
||||
int index;
|
||||
|
||||
if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
|
||||
return 0;
|
||||
|
||||
/* No more block groups to activate */
|
||||
if (space_info->active_total_bytes == space_info->total_bytes)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
bool need_finish = false;
|
||||
|
||||
down_read(&space_info->groups_sem);
|
||||
for (index = 0; index < BTRFS_NR_RAID_TYPES; index++) {
|
||||
list_for_each_entry(bg, &space_info->block_groups[index],
|
||||
list) {
|
||||
if (!spin_trylock(&bg->lock))
|
||||
continue;
|
||||
if (btrfs_zoned_bg_is_full(bg) || bg->zone_is_active) {
|
||||
spin_unlock(&bg->lock);
|
||||
continue;
|
||||
}
|
||||
spin_unlock(&bg->lock);
|
||||
|
||||
if (btrfs_zone_activate(bg)) {
|
||||
up_read(&space_info->groups_sem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
need_finish = true;
|
||||
}
|
||||
}
|
||||
up_read(&space_info->groups_sem);
|
||||
|
||||
if (!do_finish || !need_finish)
|
||||
break;
|
||||
|
||||
ret = btrfs_zone_finish_one_bg(fs_info);
|
||||
if (ret == 0)
|
||||
break;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ bool btrfs_zoned_should_reclaim(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_zoned_release_data_reloc_bg(struct btrfs_fs_info *fs_info, u64 logical,
|
||||
u64 length);
|
||||
int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_space_info *space_info, bool do_finish);
|
||||
#else /* CONFIG_BLK_DEV_ZONED */
|
||||
static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
|
||||
struct blk_zone *zone)
|
||||
@ -256,6 +258,14 @@ static inline int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_space_info *space_info,
|
||||
bool do_finish)
|
||||
{
|
||||
/* Consider all the block groups are active */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
|
||||
|
Loading…
Reference in New Issue
Block a user