Linux bcache driver list
 help / color / mirror / Atom feed
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

      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