btrfs: zoned: use greedy gc for auto reclaim

Currently auto reclaim of unusable zones reclaims the block-groups in
the order they have been added to the reclaim list.

Change this to a greedy algorithm by sorting the list so we have the
block-groups with the least amount of valid bytes reclaimed first.

Note: we can't splice the block groups from reclaim_bgs to let the sort
happen outside of the lock. The block groups can be still in use by
other parts eg. via bg_list and we must hold unused_bgs_lock while
processing them.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ write note and comment why we can't splice the list ]
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Johannes Thumshirn 2021-10-14 18:39:02 +09:00 committed by David Sterba
parent 813ebc164e
commit 2ca0ec770c

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/list_sort.h>
#include "misc.h"
#include "ctree.h"
#include "block-group.h"
@ -1486,6 +1487,21 @@ void btrfs_mark_bg_unused(struct btrfs_block_group *bg)
spin_unlock(&fs_info->unused_bgs_lock);
}
/*
* We want block groups with a low number of used bytes to be in the beginning
* of the list, so they will get reclaimed first.
*/
static int reclaim_bgs_cmp(void *unused, const struct list_head *a,
const struct list_head *b)
{
const struct btrfs_block_group *bg1, *bg2;
bg1 = list_entry(a, struct btrfs_block_group, bg_list);
bg2 = list_entry(b, struct btrfs_block_group, bg_list);
return bg1->used > bg2->used;
}
void btrfs_reclaim_bgs_work(struct work_struct *work)
{
struct btrfs_fs_info *fs_info =
@ -1510,6 +1526,12 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
}
spin_lock(&fs_info->unused_bgs_lock);
/*
* Sort happens under lock because we can't simply splice it and sort.
* The block groups might still be in use and reachable via bg_list,
* and their presence in the reclaim_bgs list must be preserved.
*/
list_sort(NULL, &fs_info->reclaim_bgs, reclaim_bgs_cmp);
while (!list_empty(&fs_info->reclaim_bgs)) {
u64 zone_unusable;
int ret = 0;