diff options
| author | Michal Grzedzicki <mge@meta.com> | 2026-03-30 09:06:44 -0700 |
|---|---|---|
| committer | David Sterba <dsterba@suse.com> | 2026-04-07 19:43:50 +0200 |
| commit | 3cd181cc46d36aa7bd4af85f14639d86a25beaec (patch) | |
| tree | 66cb6bdf632e4d7208d60697a66bc371e2deee41 | |
| parent | e0dfaebb8f4a1de59a8b805d600e3b662b235efc (diff) | |
| download | linux-3cd181cc46d36aa7bd4af85f14639d86a25beaec.tar.gz linux-3cd181cc46d36aa7bd4af85f14639d86a25beaec.zip | |
btrfs: fix silent IO error loss in encoded writes and zoned split
can_finish_ordered_extent() and btrfs_finish_ordered_zoned() set
BTRFS_ORDERED_IOERR via bare set_bit(). Later,
btrfs_mark_ordered_extent_error() in btrfs_finish_one_ordered() uses
test_and_set_bit(), finds it already set, and skips
mapping_set_error(). The error is never recorded on the inode's
address_space, making it invisible to fsync. For encoded writes this
causes btrfs receive to silently produce files with zero-filled holes.
Fix: replace bare set_bit(BTRFS_ORDERED_IOERR) with
btrfs_mark_ordered_extent_error() which pairs test_and_set_bit() with
mapping_set_error(), guaranteeing the error is recorded exactly once.
Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Mark Harmstone <mark@harmstone.com>
Signed-off-by: Michal Grzedzicki <mge@meta.com>
Signed-off-by: David Sterba <dsterba@suse.com>
| -rw-r--r-- | fs/btrfs/ordered-data.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/zoned.c | 2 |
2 files changed, 2 insertions, 2 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index d39f1c49d1cf..e5a24b3ff95e 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -386,7 +386,7 @@ static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered, } if (!uptodate) - set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); + btrfs_mark_ordered_extent_error(ordered); if (ordered->bytes_left) return false; diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index f7ca01a32a03..16dd87aa06f2 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2134,7 +2134,7 @@ void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered) continue; } if (!btrfs_zoned_split_ordered(ordered, logical, len)) { - set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); + btrfs_mark_ordered_extent_error(ordered); btrfs_err(fs_info, "failed to split ordered extent"); goto out; } |
