Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH v2] btrfs: force a transaction commit when fsyncing stripe-tree extents
@ 2026-10-22  9:06 Johannes Thumshirn
  2026-10-22  9:39 ` Damien Le Moal
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Johannes Thumshirn @ 2026-10-22  9:06 UTC (permalink / raw)
  To: linux-btrfs
  Cc: Damien Le Moal, Filipe Manana, Naohiro Aota, Johannes Thumshirn

An extent in a block-group that uses the RAID stripe-tree has its logical
to physical mapping stored in that tree, which only becomes persistent
when the stripe-tree is written out at transaction commit. But the RAID
stripe-tree is not logged in the log tree.

A fsync therefore logs a file-extent item whose logical range cannot be
resolved after a crash. Replay restores the file-extent item and the
file has the correct size, but reading it fails with EIO and nothing is
reported.

Force a full commit when logging such an extent. Extents reach the log
both from log_one_extent() and from copy_items(), so check in both.
copy_items() skips extents from a past transaction, their mapping is
already committed, the same reason their checksums are not logged.

Fixes: 02c372e1f016 ("btrfs: add support for inserting raid stripe extents")
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---

Changes to v1:
- Don't just fix the fast fsync

 fs/btrfs/tree-log.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 1d9dfb63fc5a..e50f924bca59 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -30,6 +30,8 @@
 #include "print-tree.h"
 #include "tree-checker.h"
 #include "delayed-inode.h"
+#include "volumes.h"
+#include "raid-stripe-tree.h"
 
 #define MAX_CONFLICT_INODES 10
 
@@ -4741,6 +4743,24 @@ static int log_csums(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
+static bool log_extent_needs_stripe_tree(struct btrfs_fs_info *fs_info,
+					 u64 disk_bytenr)
+{
+	struct btrfs_chunk_map *map __free(btrfs_free_chunk_map) = NULL;
+
+	if (!btrfs_fs_incompat(fs_info, RAID_STRIPE_TREE))
+		return false;
+
+	if (disk_bytenr == 0 || disk_bytenr >= EXTENT_MAP_LAST_BYTE)
+		return false;
+
+	map = btrfs_find_chunk_map(fs_info, disk_bytenr, 1);
+	if (!map)
+		return false;
+
+	return btrfs_need_stripe_tree_update(fs_info, map->type);
+}
+
 static noinline int copy_items(struct btrfs_trans_handle *trans,
 			       struct btrfs_inode *inode,
 			       struct btrfs_path *dst_path,
@@ -4847,6 +4867,14 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
 		    inode->last_reflink_trans < trans->transid)
 			continue;
 
+		if (!is_old_extent &&
+		    btrfs_file_extent_type(src, extent) != BTRFS_FILE_EXTENT_INLINE) {
+			u64 bytenr = btrfs_file_extent_disk_bytenr(src, extent);
+
+			if (log_extent_needs_stripe_tree(trans->fs_info, bytenr))
+				return BTRFS_LOG_FORCE_COMMIT;
+		}
+
 		if (skip_csum)
 			goto add_to_batch;
 
@@ -5124,6 +5152,9 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
 	u64 block_len;
 	int ret;
 
+	if (log_extent_needs_stripe_tree(inode->root->fs_info, em->disk_bytenr))
+		return BTRFS_LOG_FORCE_COMMIT;
+
 	btrfs_set_stack_file_extent_generation(&fi, trans->transid);
 	if (em->flags & EXTENT_FLAG_PREALLOC)
 		btrfs_set_stack_file_extent_type(&fi, BTRFS_FILE_EXTENT_PREALLOC);
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-22 21:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22  9:06 [PATCH v2] btrfs: force a transaction commit when fsyncing stripe-tree extents Johannes Thumshirn
2026-10-22  9:39 ` Damien Le Moal
2026-10-22 14:17 ` Filipe Manana
2026-10-22 21:09 ` Qu Wenruo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox