| From: |
| Leo Martins <loemra.dev-AT-gmail.com> |
| To: |
| linux-btrfs-AT-vger.kernel.org, kernel-team-AT-fb.com |
| Subject: |
| [PATCH 0/2] btrfs: skip COW for written extent buffers |
| Date: |
| Thu, 23 Apr 2026 15:43:32 -0700 |
| Message-ID: |
| <cover.1776899536.git.loemra.dev@gmail.com> |
| Archive-link: |
| Article |
This series adds an optimization to skip redundant COW operations on
extent buffers that were allocated in the current transaction but
already written back to disk due to memory pressure.
When writeback sets BTRFS_HEADER_FLAG_WRITTEN on a buffer, subsequent
btrfs_search_slot() calls re-COW it unnecessarily -- the committed
superblock doesn't reference blocks from the uncommitted transaction,
so overwriting in place is crash-safe. This COW amplification can
exhaust block reservations and degrade throughput under memory
pressure.
The first patch fixes a latent issue in qgroup snapshot accounting:
qgroup_account_snapshot() calls commit_fs_roots() mid-transaction to
persist root items, but commit_fs_roots() also clears
BTRFS_ROOT_FORCE_COW as a finalization step. This leaves snapshotted
roots in an incorrect state where blocks are shared via
btrfs_copy_root() but FORCE_COW no longer reflects that. This is
currently harmless because WRITTEN buffers are always COW'd, but
becomes a corruption vector once the skip-COW optimization relies on
FORCE_COW to protect shared blocks. The fix extracts the root item
persistence into qgroup_commit_fs_roots(), which does only what
qgroup accounting needs without the finalization side effects.
The second patch adds the skip-COW optimization itself, and was
previously sent and reviewed but reverted due to the qgroup
interaction fixed in patch 1. The code is unchanged from the
reviewed version. When should_cow_block() encounters a WRITTEN
buffer from the current transaction, it re-dirties the buffer and
overwrites in place instead of allocating a new block. FORCE_COW,
EXTENT_BUFFER_WRITEBACK, log trees, zoned devices, and relocation
are all excluded.
Leo Martins (2):
btrfs: don't finalize fs roots during qgroup snapshot accounting
btrfs: skip COW for written extent buffers allocated in current
transaction
fs/btrfs/ctree.c | 83 +++++++++++++++++++++++++-------
fs/btrfs/disk-io.c | 2 +-
fs/btrfs/extent_io.c | 4 --
fs/btrfs/transaction.c | 105 +++++++++++++++++++++++++++++------------
4 files changed, 142 insertions(+), 52 deletions(-)
--
2.52.0