mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 <kent.overstreet@linux.dev>
This commit is contained in:
		
							parent
							
								
									5af61dbd96
								
							
						
					
					
						commit
						3ba0240a87
					
				
					 3 changed files with 7 additions and 4 deletions
				
			
		| 
						 | 
					@ -225,11 +225,11 @@ static void bchfs_read(struct btree_trans *trans,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bch2_read_extent(trans, rbio, iter.pos,
 | 
							bch2_read_extent(trans, rbio, iter.pos,
 | 
				
			||||||
				 data_btree, k, offset_into_extent, flags);
 | 
									 data_btree, k, offset_into_extent, flags);
 | 
				
			||||||
 | 
							swap(rbio->bio.bi_iter.bi_size, bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (flags & BCH_READ_last_fragment)
 | 
							if (flags & BCH_READ_last_fragment)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		swap(rbio->bio.bi_iter.bi_size, bytes);
 | 
					 | 
				
			||||||
		bio_advance(&rbio->bio, bytes);
 | 
							bio_advance(&rbio->bio, bytes);
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
		if (ret &&
 | 
							if (ret &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
							ret = __bch2_read_extent(trans, rbio, bvec_iter, iter.pos,
 | 
				
			||||||
					 data_btree, k,
 | 
										 data_btree, k,
 | 
				
			||||||
					 offset_into_extent, failed, flags, -1);
 | 
										 offset_into_extent, failed, flags, -1);
 | 
				
			||||||
 | 
							swap(bvec_iter.bi_size, bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (flags & BCH_READ_last_fragment)
 | 
							if (flags & BCH_READ_last_fragment)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		swap(bvec_iter.bi_size, bytes);
 | 
					 | 
				
			||||||
		bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
 | 
							bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
		if (ret == -BCH_ERR_data_read_retry_csum_err_maybe_userspace)
 | 
							if (ret == -BCH_ERR_data_read_retry_csum_err_maybe_userspace)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -137,8 +137,10 @@ static inline void bch2_read_extent(struct btree_trans *trans,
 | 
				
			||||||
			enum btree_id data_btree, struct bkey_s_c k,
 | 
								enum btree_id data_btree, struct bkey_s_c k,
 | 
				
			||||||
			unsigned offset_into_extent, unsigned flags)
 | 
								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);
 | 
									     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,
 | 
					int __bch2_read(struct btree_trans *, struct bch_read_bio *, struct bvec_iter,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue