From: Kent Overstreet Date: Mon, 24 Mar 2025 15:51:01 +0000 (-0400) Subject: bcachefs: Fix silent short reads in data read retry path X-Git-Tag: v6.15-rc1~83^2~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ba0240a8789;p=thirdparty%2Flinux.git bcachefs: Fix silent short reads in data read retry path __bch2_read, before calling __bch2_read_extent(), sets bvec_iter.bi_size to "the size we can read from the current extent" with a swap, and restores it to "the size for the total read" after the read_extent call with another swap. But we neglected to do the restore before the "if (ret) goto err;" - which is a problem if we're retrying those errors. Signed-off-by: Kent Overstreet --- diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c index 5ab1c73c8d4c9..a03e2c780cba0 100644 --- a/fs/bcachefs/fs-io-buffered.c +++ b/fs/bcachefs/fs-io-buffered.c @@ -225,11 +225,11 @@ static void bchfs_read(struct btree_trans *trans, bch2_read_extent(trans, rbio, iter.pos, data_btree, k, offset_into_extent, flags); + swap(rbio->bio.bi_iter.bi_size, bytes); if (flags & BCH_READ_last_fragment) break; - swap(rbio->bio.bi_iter.bi_size, bytes); bio_advance(&rbio->bio, bytes); err: if (ret && diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c index f1503df57dc71..fafd00a3d6c95 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c @@ -1322,13 +1322,14 @@ int __bch2_read(struct btree_trans *trans, struct bch_read_bio *rbio, ret = __bch2_read_extent(trans, rbio, bvec_iter, iter.pos, data_btree, k, offset_into_extent, failed, flags, -1); + swap(bvec_iter.bi_size, bytes); + if (ret) goto err; if (flags & BCH_READ_last_fragment) break; - swap(bvec_iter.bi_size, bytes); bio_advance_iter(&rbio->bio, &bvec_iter, bytes); err: if (ret == -BCH_ERR_data_read_retry_csum_err_maybe_userspace) diff --git a/fs/bcachefs/io_read.h b/fs/bcachefs/io_read.h index cd21950417f64..c78025d863e0f 100644 --- a/fs/bcachefs/io_read.h +++ b/fs/bcachefs/io_read.h @@ -137,8 +137,10 @@ static inline void bch2_read_extent(struct btree_trans *trans, enum btree_id data_btree, struct bkey_s_c k, unsigned offset_into_extent, unsigned flags) { - __bch2_read_extent(trans, rbio, rbio->bio.bi_iter, read_pos, - data_btree, k, offset_into_extent, NULL, flags, -1); + int ret = __bch2_read_extent(trans, rbio, rbio->bio.bi_iter, read_pos, + data_btree, k, offset_into_extent, NULL, flags, -1); + /* __bch2_read_extent only returns errors if BCH_READ_in_retry is set */ + WARN(ret, "unhandled error from __bch2_read_extent()"); } int __bch2_read(struct btree_trans *, struct bch_read_bio *, struct bvec_iter,