From: Kefu Chai Date: Wed, 8 Jul 2026 05:40:15 +0000 (+0800) Subject: crimson/os/seastore: don't let a later rewrite reset force_rewrite_conflict X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6f7d167094a255e5dc0b0ac47ec38d5c4bd9ea48;p=ceph.git crimson/os/seastore: don't let a later rewrite reset force_rewrite_conflict rewrite_logical_extent() sets the flag with a plain assignment: t.force_rewrite_conflict = (extents.size() > 1); The flag marks remaps that produced multiple extents, and with them lba insertions the no-conflict publish path cannot handle. But the trimmer and the cleaner rewrite a batch of extents in one transaction (the do_for_each loops in async_cleaner.cc), so each extent overwrites what the previous one set: extent A remaps into three pieces and sets the flag, extent B remaps into one and clears it again. should_use_no_conflict_publish() then routes a transaction with structural btree changes through the publish-to-prior path the comment above this line rules out, and that path rebases concurrently built transactions incompletely, leaving them with stale mappings. Make the flag sticky with |=. It is only cleared on transaction reset, which is the intended lifetime. Introduced by 02e511c5d5d; the batch callers predate it, so the reset has been reachable from the start. Signed-off-by: Kefu Chai --- diff --git a/src/crimson/os/seastore/transaction_manager.cc b/src/crimson/os/seastore/transaction_manager.cc index 10244545a2fc..c36d1b7dbc93 100644 --- a/src/crimson/os/seastore/transaction_manager.cc +++ b/src/crimson/os/seastore/transaction_manager.cc @@ -785,8 +785,9 @@ TransactionManager::rewrite_logical_extent( // the LBA update likely involves insertions/splits (structural // btree changes), which the no-conflict publish-to-prior path // does not currently cover safely. Fall back to optimistic - // conflict handling. - t.force_rewrite_conflict = (extents.size() > 1); + // conflict handling. a batch transaction rewrites many extents, + // and any structural rewrite taints them all. + t.force_rewrite_conflict |= (extents.size() > 1); for (auto &_nextent : extents) { auto nextent = _nextent->template cast(); bool first_extent = (off == 0);