add follow-up fix for NVME driver
fixes a BUG_ON triggered by Samsung SM960 Pro NVME devices
This commit is contained in:
		
							parent
							
								
									1e9f438872
								
							
						
					
					
						commit
						c1fc04f4d1
					
				
							
								
								
									
										96
									
								
								0001-block-fix-bio_will_gap-for-first-bvec-with-offset.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								0001-block-fix-bio_will_gap-for-first-bvec-with-offset.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | From 5a8d75a1b8c99bdc926ba69b7b7dbe4fae81a5af Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ming Lei <ming.lei@redhat.com> | ||||||
|  | Date: Fri, 14 Apr 2017 13:58:29 -0600 | ||||||
|  | Subject: [PATCH] block: fix bio_will_gap() for first bvec with offset | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | Commit 729204ef49ec("block: relax check on sg gap") allows us to merge | ||||||
|  | bios, if both are physically contiguous.  This change can merge a huge | ||||||
|  | number of small bios, through mkfs for example, mkfs.ntfs running time | ||||||
|  | can be decreased to ~1/10. | ||||||
|  | 
 | ||||||
|  | But if one rq starts with a non-aligned buffer (the 1st bvec's bv_offset | ||||||
|  | is non-zero) and if we allow the merge, it is quite difficult to respect | ||||||
|  | sg gap limit, especially the max segment size, or we risk having an | ||||||
|  | unaligned virtual boundary.  This patch tries to avoid the issue by | ||||||
|  | disallowing a merge, if the req starts with an unaligned buffer. | ||||||
|  | 
 | ||||||
|  | Also add comments to explain why the merged segment can't end in | ||||||
|  | unaligned virt boundary. | ||||||
|  | 
 | ||||||
|  | Fixes: 729204ef49ec ("block: relax check on sg gap") | ||||||
|  | Tested-by: Johannes Thumshirn <jthumshirn@suse.de> | ||||||
|  | Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> | ||||||
|  | Signed-off-by: Ming Lei <ming.lei@redhat.com> | ||||||
|  | 
 | ||||||
|  | Rewrote parts of the commit message and comments. | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jens Axboe <axboe@fb.com> | ||||||
|  | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | ||||||
|  | ---
 | ||||||
|  |  include/linux/blkdev.h | 32 ++++++++++++++++++++++++++++---- | ||||||
|  |  1 file changed, 28 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
 | ||||||
|  | index 7548f332121a..01a696b0a4d3 100644
 | ||||||
|  | --- a/include/linux/blkdev.h
 | ||||||
|  | +++ b/include/linux/blkdev.h
 | ||||||
|  | @@ -1672,12 +1672,36 @@ static inline bool bios_segs_mergeable(struct request_queue *q,
 | ||||||
|  |  	return true; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
 | ||||||
|  | -			 struct bio *next)
 | ||||||
|  | +static inline bool bio_will_gap(struct request_queue *q,
 | ||||||
|  | +				struct request *prev_rq,
 | ||||||
|  | +				struct bio *prev,
 | ||||||
|  | +				struct bio *next)
 | ||||||
|  |  { | ||||||
|  |  	if (bio_has_data(prev) && queue_virt_boundary(q)) { | ||||||
|  |  		struct bio_vec pb, nb; | ||||||
|  |   | ||||||
|  | +		/*
 | ||||||
|  | +		 * don't merge if the 1st bio starts with non-zero
 | ||||||
|  | +		 * offset, otherwise it is quite difficult to respect
 | ||||||
|  | +		 * sg gap limit. We work hard to merge a huge number of small
 | ||||||
|  | +		 * single bios in case of mkfs.
 | ||||||
|  | +		 */
 | ||||||
|  | +		if (prev_rq)
 | ||||||
|  | +			bio_get_first_bvec(prev_rq->bio, &pb);
 | ||||||
|  | +		else
 | ||||||
|  | +			bio_get_first_bvec(prev, &pb);
 | ||||||
|  | +		if (pb.bv_offset)
 | ||||||
|  | +			return true;
 | ||||||
|  | +
 | ||||||
|  | +		/*
 | ||||||
|  | +		 * We don't need to worry about the situation that the
 | ||||||
|  | +		 * merged segment ends in unaligned virt boundary:
 | ||||||
|  | +		 *
 | ||||||
|  | +		 * - if 'pb' ends aligned, the merged segment ends aligned
 | ||||||
|  | +		 * - if 'pb' ends unaligned, the next bio must include
 | ||||||
|  | +		 *   one single bvec of 'nb', otherwise the 'nb' can't
 | ||||||
|  | +		 *   merge with 'pb'
 | ||||||
|  | +		 */
 | ||||||
|  |  		bio_get_last_bvec(prev, &pb); | ||||||
|  |  		bio_get_first_bvec(next, &nb); | ||||||
|  |   | ||||||
|  | @@ -1690,12 +1714,12 @@ static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
 | ||||||
|  |   | ||||||
|  |  static inline bool req_gap_back_merge(struct request *req, struct bio *bio) | ||||||
|  |  { | ||||||
|  | -	return bio_will_gap(req->q, req->biotail, bio);
 | ||||||
|  | +	return bio_will_gap(req->q, req, req->biotail, bio);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static inline bool req_gap_front_merge(struct request *req, struct bio *bio) | ||||||
|  |  { | ||||||
|  | -	return bio_will_gap(req->q, bio, req->bio);
 | ||||||
|  | +	return bio_will_gap(req->q, NULL, bio, req->bio);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  int kblockd_schedule_work(struct work_struct *work); | ||||||
|  | -- 
 | ||||||
|  | 2.11.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @ -250,6 +250,7 @@ ${KERNEL_SRC}/README: ${KERNEL_SRC_SUBMODULE} | submodules | |||||||
| 	cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-1000365-fs-exec.c-account-for-argv-envp-pointers.patch | 	cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-1000365-fs-exec.c-account-for-argv-envp-pointers.patch | ||||||
| 	cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-10810-drm-virtio-don-t-leak-bo-on-drm_gem_object_init-fail.patch | 	cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-10810-drm-virtio-don-t-leak-bo-on-drm_gem_object_init-fail.patch | ||||||
| 	cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch | 	cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch | ||||||
|  | 	cd ${KERNEL_SRC}; patch -p1 < ../0001-block-fix-bio_will_gap-for-first-bvec-with-offset.patch | ||||||
| 	sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' | 	sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' | ||||||
| 	touch $@ | 	touch $@ | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Fabian Grünbichler
						Fabian Grünbichler