From: "Zhou Jifeng" <zhoujifeng@kylinos.com.cn>
To: "Coly Li" <colyli@fygo.io>
Cc: linux-bcache <linux-bcache@vger.kernel.org>
Subject: Re: [PATCH RFC v4] bcache: flush backing device before cleaning the writeback dirty keys
Date: Fri, 10 Jul 2026 18:17:18 +0800 [thread overview]
Message-ID: <tencent_3964FC886EF21A2B778D4DC8@qq.com> (raw)
In-Reply-To: <5FF95998-80AD-4E84-8022-A2D0C75939B7@fygo.io>
>> 2026年7月9日 14:23,Zhou Jifeng <zhoujifeng@kylinos.com.cn> 写道:
>>
>> From: Zhou Jifeng <zhoujifeng@kylinsec.com.cn>
>>
>> Currently, when writeback dirty data completes, write_dirty_finish()
>> immediately inserts the clean key into the btree. If a power failure
>> occurs after the clean-key insert but before the backing device has
>> flushed its volatile write cache, the btree contains a clean key that
>> points at backing data that never reached stable media. On the next
>> read, bcache serves stale data from the backing device.
>>
>> Fix this by deferring the clean-key btree insert until after an
>> explicit backing-device flush (REQ_PREFLUSH). Written keys are first
>> parked in a new rbtree (writeback_flush_pending) keyed by START_KEY.
>> After enough read_dirty() passes, a full btree scan, or a wrap-around
>> in refill_dirty(), writeback_finish_batch() issues a synchronous
>> backing-device flush, and only on success inserts the clean keys into
>> the btree and removes them from the pending tree. On flush failure
>> the entries are re-inserted into the current tree for a later retry.
>>
>> Key changes:
>>
>> - Introduce struct writeback_pending (separate kmalloc'd allocation,
>> decoupled from the dirty_io closure so the closure can be freed
>> immediately and the pending entry lives until the flush).
>>
>> - Add __writeback_pending_insert() — inserts into the START_KEY-
>> ordered rbtree with overlap detection. The rbtree is also used as
>> an interval tree by bch_writeback_drop_pending() for front-end
>> write overlap queries; that search is correct only because dirty
>> btree keys are pairwise disjoint, an invariant enforced at insert
>> time.
>>
>> - writeback_add_to_pending() parks a key after successful writeback
>> IO. Uses GFP_NOIO because the caller runs on the WQ_MEM_RECLAIM
>> writeback workqueue. kmalloc failure silently drops the key (it
>> stays dirty and is re-selected by the next scan).
>>
>> - writeback_finish_batch() detaches the entire pending tree into a
>> local list under spinlock, issues writeback_flush(), then either
>> cleans the keys (on success) or re-inserts them (on failure).
>>
>> - writeback_flush() open-codes blkdev_issue_flush() to call
>> bch_count_backing_io_errors() on failure.
>>
>> - bch_writeback_drop_pending() drops overlapping entries from the
>> pending tree. Called from cached_dev_write() alongside the
>> existing bch_keybuf_check_overlapping(); overlapping front-end
>> writes now force writeback instead of bypassing the cache.
>>
>> - refill_dirty() now returns enum writeback_scan_result (PARTIAL,
>> PARTIAL_WRAP, FULL_SEARCHED) instead of a boolean. Before
>> wrapping around for a second scan pass, it flushes the pending
>> tree so the wrap scan won't re-select keys that are still
>> KEY_DIRTY in the btree but already written to backing and
>> awaiting flush. writeback_lock may be transiently released
>> mid-function during this pre-wrap flush.
>>
>> - refill_full_stripes() no longer wraps internally; it returns
>> at the end of the stripe range and delegates the wrap to
>> refill_dirty(). buf->last_scanned is no longer rewound past
>> the current position to avoid re-selecting keys already in
>> writeback_flush_pending.
>>
>> - read_dirty() gates deferred flush-and-clean on PASS_PER_FLUSH
>> (default 5) passes, a full btree scan, or a PARTIAL_WRAP. It
>> accepts the scan_result from refill_dirty() as a parameter.
>>
>> - write_dirty_finish() is simplified: it no longer inserts clean
>> keys inline; it only calls writeback_add_to_pending().
>>
>> - BDEV_STATE_CLEAN eligibility in the main loop now also requires
>> writeback_pending_empty(), so a device is not marked clean while
>> entries are still in the pending tree.
>>
>> - Thread exit: the workqueue is destroyed first, then a final
>> writeback_finish_batch() is attempted (skipped when the cache
>> set is disabled or the device is detaching), then any remaining
>> pending entries are drained. The exit path intentionally does
>> NOT set BDEV_STATE_CLEAN because it lacks the WB_SCAN_FULL_SEARCHED
>> gate that the in-loop check requires; a kthread_stop mid-scan
>> (e.g. from bch_cached_dev_attach's error path) must not mark a
>> still-dirty device clean.
>>
>> Signed-off-by: Coly Li <colyli@fygo.io>
>> Signed-off-by: Zhou Jifeng <zhoujifeng@kylinsec.com.cn>
>
> You cannot add my SOB for me. I know you mean the base idea of this version was
> from me, but it is fine to only do your own SOB. I am good with this, since you already
> do a lot of analysis and testing.
>
> The v4 version format is much more easier to review.
> I will try my best to response you soon.
>
> Thanks for the fix up and testing.
>
> Coly Li
Hi Coly,
I really appreciate your time and guidance on this patch.
Best regards,
Zhou Jifeng
prev parent reply other threads:[~2026-07-10 10:17 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 8:27 [PATCH RFC v3] bcache: flush backing device before cleaning the writeback dirty keys Zhou Jifeng
2026-07-08 3:56 ` Coly Li
2026-07-09 6:23 ` [PATCH RFC v4] " Zhou Jifeng
2026-07-09 6:30 ` Coly Li
2026-07-10 10:17 ` Zhou Jifeng [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tencent_3964FC886EF21A2B778D4DC8@qq.com \
--to=zhoujifeng@kylinos.com.cn \
--cc=colyli@fygo.io \
--cc=linux-bcache@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox