Messages in this thread | ![/](/images/icornerl.gif) | | From | Naohiro Aota <> | Subject | Re: [PATCH RFC PATCH 2/3] btrfs: zoned: reserve relocation zone on mount | Date | Fri, 5 Apr 2024 01:14:01 +0000 |
| |
On Thu, Mar 28, 2024 at 02:56:32PM +0100, Johannes Thumshirn wrote: > From: Johannes Thumshirn <johannes.thumshirn@wdc.com> > > Reserve one zone as a data relocation target on each mount. If we already > find one empty block group, there's no need to force a chunk allocation, > but we can use this empty data block group as our relocation target. > > Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> > --- > fs/btrfs/disk-io.c | 2 ++ > fs/btrfs/zoned.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ > fs/btrfs/zoned.h | 3 +++ > 3 files changed, 51 insertions(+) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 5a35c2c0bbc9..83b56f109d29 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -3550,6 +3550,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device > } > btrfs_discard_resume(fs_info); > > + btrfs_reserve_relocation_zone(fs_info); > + > if (fs_info->uuid_root && > (btrfs_test_opt(fs_info, RESCAN_UUID_TREE) || > fs_info->generation != btrfs_super_uuid_tree_generation(disk_super))) { > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > index d51faf7f4162..fb8707f4cab5 100644 > --- a/fs/btrfs/zoned.c > +++ b/fs/btrfs/zoned.c > @@ -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 > @@ -2634,3 +2635,48 @@ void btrfs_check_active_zone_reservation(struct btrfs_fs_info *fs_info) > } > spin_unlock(&fs_info->zone_active_bgs_lock); > } > + > +static u64 find_empty_block_group(struct btrfs_space_info *sinfo) > +{ > + struct btrfs_block_group *bg; > + > + for (int i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
This starting index prefers SINGLE to DUP/RAID profiles, which is bad. We can use something like get_alloc_profile_by_root() to decide a proper starting index.
> + list_for_each_entry(bg, &sinfo->block_groups[i], list) { > + if (bg->used == 0) > + return bg->start; > + } > + } > + > + return 0; > +} > + > +void btrfs_reserve_relocation_zone(struct btrfs_fs_info *fs_info) > +{ > + struct btrfs_root *tree_root = fs_info->tree_root; > + struct btrfs_space_info *sinfo = fs_info->data_sinfo; > + struct btrfs_trans_handle *trans; > + u64 flags = btrfs_get_alloc_profile(fs_info, sinfo->flags); > + u64 bytenr = 0; > + > + if (!btrfs_is_zoned(fs_info)) > + return; > + > + bytenr = find_empty_block_group(sinfo); > + if (!bytenr) { > + int ret; > + > + trans = btrfs_join_transaction(tree_root); > + if (IS_ERR(trans)) > + return; > + > + ret = btrfs_chunk_alloc(trans, flags, CHUNK_ALLOC_FORCE); > + btrfs_end_transaction(trans); > + > + if (!ret) > + bytenr = find_empty_block_group(sinfo); > + } > + > + spin_lock(&fs_info->relocation_bg_lock);
Currently, this function is called in the mount process: there is no relocation BG set. To prevent future misuse, I'd like to add an ASSERT(fs_info->relocation_bg_lock == 0).
> + fs_info->data_reloc_bg = bytenr;
We can activate that block group as well to ensure it's ready to go.
> + spin_unlock(&fs_info->relocation_bg_lock); > +} > diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h > index 77c4321e331f..048ffada4549 100644 > --- a/fs/btrfs/zoned.h > +++ b/fs/btrfs/zoned.h > @@ -97,6 +97,7 @@ 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); > void btrfs_check_active_zone_reservation(struct btrfs_fs_info *fs_info); > +void btrfs_reserve_relocation_zone(struct btrfs_fs_info *fs_info); > #else /* CONFIG_BLK_DEV_ZONED */ > static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, > struct blk_zone *zone) > @@ -271,6 +272,8 @@ static inline int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info, > > static inline void btrfs_check_active_zone_reservation(struct btrfs_fs_info *fs_info) { } > > +static inline void btrfs_reserve_relocation_zone(struct btrfs_fs_info *fs_info) { } > + > #endif > > static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos) > > -- > 2.35.3 >
| ![\](/images/icornerr.gif) |