Commit 3ba0240a authored by Kent Overstreet's avatar Kent Overstreet
Browse files

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 5af61dbd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 &&
+2 −1
Original line number Diff line number Diff line
@@ -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)
+4 −2
Original line number Diff line number Diff line
@@ -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,
	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,