Skip to content

Commit 3dac103

Browse files
morbidrsakdave
authored andcommitted
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. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 90515fe commit 3dac103

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,6 +3561,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
35613561
goto fail_sysfs;
35623562
}
35633563

3564+
btrfs_zoned_reserve_data_reloc_bg(fs_info);
35643565
btrfs_free_zone_cache(fs_info);
35653566

35663567
btrfs_check_active_zone_reservation(fs_info);

fs/btrfs/zoned.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "fs.h"
1818
#include "accessors.h"
1919
#include "bio.h"
20+
#include "transaction.h"
2021

2122
/* Maximum number of zones to report per blkdev_report_zones() call */
2223
#define BTRFS_REPORT_NR_ZONES 4096
@@ -2501,6 +2502,66 @@ void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg)
25012502
spin_unlock(&fs_info->relocation_bg_lock);
25022503
}
25032504

2505+
void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info)
2506+
{
2507+
struct btrfs_space_info *data_sinfo = fs_info->data_sinfo;
2508+
struct btrfs_space_info *space_info = data_sinfo->sub_group[0];
2509+
struct btrfs_trans_handle *trans;
2510+
struct btrfs_block_group *bg;
2511+
struct list_head *bg_list;
2512+
u64 alloc_flags;
2513+
bool initial = false;
2514+
bool did_chunk_alloc = false;
2515+
int index;
2516+
int ret;
2517+
2518+
if (!btrfs_is_zoned(fs_info))
2519+
return;
2520+
2521+
if (fs_info->data_reloc_bg)
2522+
return;
2523+
2524+
if (sb_rdonly(fs_info->sb))
2525+
return;
2526+
2527+
ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC);
2528+
alloc_flags = btrfs_get_alloc_profile(fs_info, space_info->flags);
2529+
index = btrfs_bg_flags_to_raid_index(alloc_flags);
2530+
2531+
bg_list = &data_sinfo->block_groups[index];
2532+
again:
2533+
list_for_each_entry(bg, bg_list, list) {
2534+
if (bg->used > 0)
2535+
continue;
2536+
2537+
if (!initial) {
2538+
initial = true;
2539+
continue;
2540+
}
2541+
2542+
fs_info->data_reloc_bg = bg->start;
2543+
set_bit(BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, &bg->runtime_flags);
2544+
btrfs_zone_activate(bg);
2545+
2546+
return;
2547+
}
2548+
2549+
if (did_chunk_alloc)
2550+
return;
2551+
2552+
trans = btrfs_join_transaction(fs_info->tree_root);
2553+
if (IS_ERR(trans))
2554+
return;
2555+
2556+
ret = btrfs_chunk_alloc(trans, space_info, alloc_flags, CHUNK_ALLOC_FORCE);
2557+
btrfs_end_transaction(trans);
2558+
if (ret == 1) {
2559+
did_chunk_alloc = true;
2560+
bg_list = &space_info->block_groups[index];
2561+
goto again;
2562+
}
2563+
}
2564+
25042565
void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info)
25052566
{
25062567
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;

fs/btrfs/zoned.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical,
8888
void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg,
8989
struct extent_buffer *eb);
9090
void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg);
91+
void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info);
9192
void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info);
9293
bool btrfs_zoned_should_reclaim(const struct btrfs_fs_info *fs_info);
9394
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,
241242

242243
static inline void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) { }
243244

245+
static inline void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) { }
246+
244247
static inline void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info) { }
245248

246249
static inline bool btrfs_zoned_should_reclaim(const struct btrfs_fs_info *fs_info)

0 commit comments

Comments
 (0)