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; | ||||
| 
 | ||||
| 	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; | ||||
| 
 | ||||
| 
 | ||||
| @ -138,7 +131,6 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq) | ||||
| 	} else { | ||||
| 		uio->uio_bvec = NULL; | ||||
| 		uio->uio_iovcnt = 0; | ||||
| 		memset(&uio->iter, 0, sizeof (uio->iter)); | ||||
| 	} | ||||
| 
 | ||||
| 	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; | ||||
| 
 | ||||
| 	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 | ||||
| 		 * 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 */ | ||||
| 		} | ||||
| 
 | ||||
| 		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; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Tony Hutter
						Tony Hutter