Re: [PATCH] bcache: allow more bucket reclaims during garbage collection
From: Robert Pang
Date: Tue Nov 03 2026 - 16:58:27 EST
On Mon, Nov 2, 2026 at 11:02 PM Robert Pang <robertpang@xxxxxxxxxx> wrote:
>
> In patch a14a68b76954 ("bcache: allow allocator to invalidate bucket in gc"),
> reclaimable buckets are added to the free list for the bucket allocator
> at the start of a GC cycle.
>
> However, once these buckets are allocated, they are no longer marked as
> reclaimable until the GC cycle finishes. Under heavy loads and frequent cache
> updates, all reclaimable buckets can be exhausted before the GC ends, causing
> the allocator to wait and stalling incoming I/O.
>
> Address this by allowing reclaimable buckets to be reclaimed during GC up to
> the number of generations left before BUCKET_GC_GEN_MAX.
>
> Signed-off-by: Robert Pang <robertpang@xxxxxxxxxx>
> ---
> drivers/md/bcache/alloc.c | 3 ++-
> drivers/md/bcache/bcache.h | 2 +-
> drivers/md/bcache/btree.c | 5 +++--
> 3 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
> index 3ec240ec685d..959d753e7cf6 100644
> --- a/drivers/md/bcache/alloc.c
> +++ b/drivers/md/bcache/alloc.c
> @@ -141,7 +141,8 @@ void __bch_invalidate_one_bucket(struct cache *ca, struct bucket *b)
> bch_inc_gen(ca, b);
> b->prio = INITIAL_PRIO;
> atomic_inc(&b->pin);
> - b->reclaimable_in_gc = 0;
> + if (b->reclaimable_in_gc)
> + b->reclaimable_in_gc--;
> }
>
> static void bch_invalidate_one_bucket(struct cache *ca, struct bucket *b)
> diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
> index ec9ff9715081..daae5ac5ffbc 100644
> --- a/drivers/md/bcache/bcache.h
> +++ b/drivers/md/bcache/bcache.h
> @@ -200,7 +200,7 @@ struct bucket {
> uint8_t gen;
> uint8_t last_gc; /* Most out of date gen in the btree */
> uint16_t gc_mark; /* Bitfield used by GC. See below for field */
> - uint16_t reclaimable_in_gc:1;
> + uint8_t reclaimable_in_gc; /* no. of times reclaimable in GC */
> };
>
> /*
> diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
> index 27a129d47d0a..fc167868c814 100644
> --- a/drivers/md/bcache/btree.c
> +++ b/drivers/md/bcache/btree.c
> @@ -1742,9 +1742,10 @@ static void btree_gc_start(struct cache_set *c)
>
> ca = c->cache;
> for_each_bucket(b, ca) {
> - b->last_gc = b->gen;
> if (bch_can_invalidate_bucket(ca, b))
> - b->reclaimable_in_gc = 1;
> + b->reclaimable_in_gc =
> + BUCKET_GC_GEN_MAX - bucket_gc_gen(b);
> + b->last_gc = b->gen;
> if (!atomic_read(&b->pin)) {
> SET_GC_MARK(b, 0);
> SET_GC_SECTORS_USED(b, 0);
> --
> 2.56.0.398.g882cbad275-goog
>
Hi all,
To provide some additional context on this patch:
- This commit fixes a recurrence of the I/O stall issue [1]
originally addressed by commit a14a68b76954 ("bcache: allow allocator
to invalidate bucket in gc").
- The recurrence stems from commit 009073806fbc ("bcache: reduce gc
latency by processing less nodes and sleep less time"), which
introduces longer GC pauses (100 ms) to reduce front IO tail latency
during GC.
- Due to the longer GC runtime, commit a14a68b76954 becomes
ineffective under heavy cache updates because reclaimable buckets are
rapidly exhausted when each bucket is limited to a single reclaim.
- This patch extends commit a14a68b76954 to allow buckets to be
reclaimed multiple times, bounded by the BUCKET_GC_GEN_MAX safety
range.
Best regards
Robert Pang
[1] https://lore.kernel.org/linux-bcache/1599736884-5479-1-git-send-email-dongsheng.yang@xxxxxxxxxxxx/