mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	zvol: Remove broken blk-mq optimization
This fix removes a dubious optimization in zfs_uiomove_bvec_rq() that saved the iterator contents of a rq_for_each_segment(). This optimization allowed restoring the "saved state" from a previous rq_for_each_segment() call on the same uio so that you wouldn't need to iterate though each bvec on every zfs_uiomove_bvec_rq() call. However, if the kernel is manipulating the requests/bios/bvecs under the covers between zfs_uiomove_bvec_rq() calls, then it could result in corruption from using the "saved state". This optimization results in an unbootable system after installing an OS on a zvol with blk-mq enabled. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tony Hutter <hutter2@llnl.gov> Closes #15351
This commit is contained in:
		
							parent
							
								
									86c3ed40e1
								
							
						
					
					
						commit
						e860cb0200
					
				| @ -73,13 +73,6 @@ typedef struct zfs_uio { | |||||||
| 	size_t		uio_skip; | 	size_t		uio_skip; | ||||||
| 
 | 
 | ||||||
| 	struct request	*rq; | 	struct request	*rq; | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * Used for saving rq_for_each_segment() state between calls |  | ||||||
| 	 * to zfs_uiomove_bvec_rq(). |  | ||||||
| 	 */ |  | ||||||
| 	struct req_iterator iter; |  | ||||||
| 	struct bio_vec bv; |  | ||||||
| } zfs_uio_t; | } zfs_uio_t; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -138,7 +131,6 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq) | |||||||
| 	} else { | 	} else { | ||||||
| 		uio->uio_bvec = NULL; | 		uio->uio_bvec = NULL; | ||||||
| 		uio->uio_iovcnt = 0; | 		uio->uio_iovcnt = 0; | ||||||
| 		memset(&uio->iter, 0, sizeof (uio->iter)); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	uio->uio_loffset = io_offset(bio, rq); | 	uio->uio_loffset = io_offset(bio, rq); | ||||||
|  | |||||||
| @ -204,22 +204,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio) | |||||||
| 	this_seg_start = orig_loffset; | 	this_seg_start = orig_loffset; | ||||||
| 
 | 
 | ||||||
| 	rq_for_each_segment(bv, rq, iter) { | 	rq_for_each_segment(bv, rq, iter) { | ||||||
| 		if (uio->iter.bio) { |  | ||||||
| 			/*
 |  | ||||||
| 			 * If uio->iter.bio is present, then we know we've saved |  | ||||||
| 			 * uio->iter from a previous call to this function, and |  | ||||||
| 			 * we can skip ahead in this rq_for_each_segment() loop |  | ||||||
| 			 * to where we last left off.  That way, we don't need |  | ||||||
| 			 * to iterate over tons of segments we've already |  | ||||||
| 			 * processed - we can just restore the "saved state". |  | ||||||
| 			 */ |  | ||||||
| 			iter = uio->iter; |  | ||||||
| 			bv = uio->bv; |  | ||||||
| 			this_seg_start = uio->uio_loffset; |  | ||||||
| 			memset(&uio->iter, 0, sizeof (uio->iter)); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Lookup what the logical offset of the last byte of this | 		 * Lookup what the logical offset of the last byte of this | ||||||
| 		 * segment is. | 		 * segment is. | ||||||
| @ -260,19 +244,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio) | |||||||
| 			copied = 1;	/* We copied some data */ | 			copied = 1;	/* We copied some data */ | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (n == 0) { |  | ||||||
| 			/*
 |  | ||||||
| 			 * All done copying.  Save our 'iter' value to the uio. |  | ||||||
| 			 * This allows us to "save our state" and skip ahead in |  | ||||||
| 			 * the rq_for_each_segment() loop the next time we call |  | ||||||
| 			 * call zfs_uiomove_bvec_rq() on this uio (which we |  | ||||||
| 			 * will be doing for any remaining data in the uio). |  | ||||||
| 			 */ |  | ||||||
| 			uio->iter = iter; /* make a copy of the struct data */ |  | ||||||
| 			uio->bv = bv; |  | ||||||
| 			return (0); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		this_seg_start = this_seg_end + 1; | 		this_seg_start = this_seg_end + 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Tony Hutter
						Tony Hutter