Commit 05356938 authored by Coly Li's avatar Coly Li Committed by Jens Axboe

bcache: call force_wake_up_gc() if necessary in check_should_bypass()

If there are extreme heavy write I/O continuously hit on relative small
cache device (512GB in my testing), it is possible to make counter
c->gc_stats.in_use continue to increase and exceed CUTOFF_CACHE_ADD.

If 'c->gc_stats.in_use > CUTOFF_CACHE_ADD' happens, all following write
requests will bypass the cache device because check_should_bypass()
returns 'true'. Because all writes bypass the cache device, counter
c->sectors_to_gc has no chance to be negative value, and garbage
collection thread won't be waken up even the whole cache becomes clean
after writeback accomplished. The aftermath is that all write I/Os go
directly into backing device even the cache device is clean.

To avoid the above situation, this patch uses a quite conservative way
to fix: if 'c->gc_stats.in_use > CUTOFF_CACHE_ADD' happens, only wakes
up garbage collection thread when the whole cache device is clean.

Before the fix, the writes-always-bypass situation happens after 10+
hours write I/O pressure on 512GB Intel optane memory which acts as
cache device. After this fix, such situation doesn't happen after 36+
hours testing.
Signed-off-by: default avatarColy Li <colyli@suse.de>
Link: https://lore.kernel.org/r/20240528120914.28705-3-colyli@suse.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent a14a68b7
...@@ -369,10 +369,24 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) ...@@ -369,10 +369,24 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
struct io *i; struct io *i;
if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) || if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
c->gc_stats.in_use > CUTOFF_CACHE_ADD ||
(bio_op(bio) == REQ_OP_DISCARD)) (bio_op(bio) == REQ_OP_DISCARD))
goto skip; goto skip;
if (c->gc_stats.in_use > CUTOFF_CACHE_ADD) {
/*
* If cached buckets are all clean now, 'true' will be
* returned and all requests will bypass the cache device.
* Then c->sectors_to_gc has no chance to be negative, and
* gc thread won't wake up and caching won't work forever.
* Here call force_wake_up_gc() to avoid such aftermath.
*/
if (BDEV_STATE(&dc->sb) == BDEV_STATE_CLEAN &&
c->gc_mark_valid)
force_wake_up_gc(c);
goto skip;
}
if (mode == CACHE_MODE_NONE || if (mode == CACHE_MODE_NONE ||
(mode == CACHE_MODE_WRITEAROUND && (mode == CACHE_MODE_WRITEAROUND &&
op_is_write(bio_op(bio)))) op_is_write(bio_op(bio))))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment