Skip to content

Commit 0e962e7

Browse files
boryaskdave
authored andcommitted
btrfs: urgent periodic reclaim pass
Periodic reclaim attempts to avoid block_groups seeing active use with a sweep mark that gets cleared on allocation and set on a sweep. In urgent conditions where we have very little unallocated space (less than one chunk used by the threshold calculation for the unallocated target), we want to be able to override this mechanism. Introduce a second pass that only happens if we fail to find a reclaim candidate and reclaim is urgent. In that case, do a second pass where all block groups are eligible. Reviewed-by: Josef Bacik <[email protected]> Signed-off-by: Boris Burkov <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 813d4c6 commit 0e962e7

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

fs/btrfs/space-info.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1972,32 +1972,65 @@ int btrfs_calc_reclaim_threshold(struct btrfs_space_info *space_info)
19721972
return READ_ONCE(space_info->bg_reclaim_threshold);
19731973
}
19741974

1975+
/*
1976+
* Under "urgent" reclaim, we will reclaim even fresh block groups that have
1977+
* recently seen successful allocations, as we are desperate to reclaim
1978+
* whatever we can to avoid ENOSPC in a transaction leading to a readonly fs.
1979+
*/
1980+
static bool is_reclaim_urgent(struct btrfs_space_info *space_info)
1981+
{
1982+
struct btrfs_fs_info *fs_info = space_info->fs_info;
1983+
u64 unalloc = atomic64_read(&fs_info->free_chunk_space);
1984+
u64 data_chunk_size = calc_effective_data_chunk_size(fs_info);
1985+
1986+
return unalloc < data_chunk_size;
1987+
}
1988+
19751989
static int do_reclaim_sweep(struct btrfs_fs_info *fs_info,
19761990
struct btrfs_space_info *space_info, int raid)
19771991
{
19781992
struct btrfs_block_group *bg;
19791993
int thresh_pct;
1994+
bool try_again = true;
1995+
bool urgent;
19801996

19811997
spin_lock(&space_info->lock);
1998+
urgent = is_reclaim_urgent(space_info);
19821999
thresh_pct = btrfs_calc_reclaim_threshold(space_info);
19832000
spin_unlock(&space_info->lock);
19842001

19852002
down_read(&space_info->groups_sem);
2003+
again:
19862004
list_for_each_entry(bg, &space_info->block_groups[raid], list) {
19872005
u64 thresh;
19882006
bool reclaim = false;
19892007

19902008
btrfs_get_block_group(bg);
19912009
spin_lock(&bg->lock);
19922010
thresh = mult_perc(bg->length, thresh_pct);
1993-
if (bg->used < thresh && bg->reclaim_mark)
2011+
if (bg->used < thresh && bg->reclaim_mark) {
2012+
try_again = false;
19942013
reclaim = true;
2014+
}
19952015
bg->reclaim_mark++;
19962016
spin_unlock(&bg->lock);
19972017
if (reclaim)
19982018
btrfs_mark_bg_to_reclaim(bg);
19992019
btrfs_put_block_group(bg);
20002020
}
2021+
2022+
/*
2023+
* In situations where we are very motivated to reclaim (low unalloc)
2024+
* use two passes to make the reclaim mark check best effort.
2025+
*
2026+
* If we have any staler groups, we don't touch the fresher ones, but if we
2027+
* really need a block group, do take a fresh one.
2028+
*/
2029+
if (try_again && urgent) {
2030+
try_again = false;
2031+
goto again;
2032+
}
2033+
20012034
up_read(&space_info->groups_sem);
20022035
return 0;
20032036
}

0 commit comments

Comments
 (0)