btrfs: zoned: reserve data_reloc block group on mount
Create a block group dedicated for data relocation on mount of a zoned filesystem. If there is already more than one empty DATA block group on mount, this one is picked for the data relocation block group, instead of a newly created one. This is done to ensure, there is always space for performing garbage collection and the filesystem is not hitting ENOSPC under heavy overwrite workloads. CC: stable@vger.kernel.org # 6.6+ Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
f1f22dfbea
commit
694ce5e143
|
|
@ -3561,6 +3561,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
|
|||
goto fail_sysfs;
|
||||
}
|
||||
|
||||
btrfs_zoned_reserve_data_reloc_bg(fs_info);
|
||||
btrfs_free_zone_cache(fs_info);
|
||||
|
||||
btrfs_check_active_zone_reservation(fs_info);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "fs.h"
|
||||
#include "accessors.h"
|
||||
#include "bio.h"
|
||||
#include "transaction.h"
|
||||
|
||||
/* Maximum number of zones to report per blkdev_report_zones() call */
|
||||
#define BTRFS_REPORT_NR_ZONES 4096
|
||||
|
|
@ -2501,6 +2502,66 @@ void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg)
|
|||
spin_unlock(&fs_info->relocation_bg_lock);
|
||||
}
|
||||
|
||||
void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_space_info *data_sinfo = fs_info->data_sinfo;
|
||||
struct btrfs_space_info *space_info = data_sinfo->sub_group[0];
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_block_group *bg;
|
||||
struct list_head *bg_list;
|
||||
u64 alloc_flags;
|
||||
bool initial = false;
|
||||
bool did_chunk_alloc = false;
|
||||
int index;
|
||||
int ret;
|
||||
|
||||
if (!btrfs_is_zoned(fs_info))
|
||||
return;
|
||||
|
||||
if (fs_info->data_reloc_bg)
|
||||
return;
|
||||
|
||||
if (sb_rdonly(fs_info->sb))
|
||||
return;
|
||||
|
||||
ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC);
|
||||
alloc_flags = btrfs_get_alloc_profile(fs_info, space_info->flags);
|
||||
index = btrfs_bg_flags_to_raid_index(alloc_flags);
|
||||
|
||||
bg_list = &data_sinfo->block_groups[index];
|
||||
again:
|
||||
list_for_each_entry(bg, bg_list, list) {
|
||||
if (bg->used > 0)
|
||||
continue;
|
||||
|
||||
if (!initial) {
|
||||
initial = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
fs_info->data_reloc_bg = bg->start;
|
||||
set_bit(BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, &bg->runtime_flags);
|
||||
btrfs_zone_activate(bg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (did_chunk_alloc)
|
||||
return;
|
||||
|
||||
trans = btrfs_join_transaction(fs_info->tree_root);
|
||||
if (IS_ERR(trans))
|
||||
return;
|
||||
|
||||
ret = btrfs_chunk_alloc(trans, space_info, alloc_flags, CHUNK_ALLOC_FORCE);
|
||||
btrfs_end_transaction(trans);
|
||||
if (ret == 1) {
|
||||
did_chunk_alloc = true;
|
||||
bg_list = &space_info->block_groups[index];
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical,
|
|||
void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg,
|
||||
struct extent_buffer *eb);
|
||||
void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg);
|
||||
void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info);
|
||||
bool btrfs_zoned_should_reclaim(const struct btrfs_fs_info *fs_info);
|
||||
void btrfs_zoned_release_data_reloc_bg(struct btrfs_fs_info *fs_info, u64 logical,
|
||||
|
|
@ -241,6 +242,8 @@ static inline void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg,
|
|||
|
||||
static inline void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) { }
|
||||
|
||||
static inline void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) { }
|
||||
|
||||
static inline void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info) { }
|
||||
|
||||
static inline bool btrfs_zoned_should_reclaim(const struct btrfs_fs_info *fs_info)
|
||||
|
|
|
|||
Loading…
Reference in New Issue