[PATCH] dm: bio split bvec fix
The code that handles bios that span table target boundaries by breaking them up into smaller bios will not split an individual struct bio_vec into more than two pieces. Sometimes more than that are required. This patch adds a loop to break the second piece up into as many pieces as are necessary. Cc: "Abhishek Gupta" <abhishekgupt@gmail.com> Cc: Dan Smith <danms@us.ibm.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
					parent
					
						
							
								06f9d4f94a
							
						
					
				
			
			
				commit
				
					
						d2044a94e8
					
				
			
		
					 1 changed files with 23 additions and 18 deletions
				
			
		| 
						 | 
					@ -533,30 +533,35 @@ static void __clone_and_map(struct clone_info *ci)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Create two copy bios to deal with io that has
 | 
							 * Handle a bvec that must be split between two or more targets.
 | 
				
			||||||
		 * been split across a target.
 | 
					 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		struct bio_vec *bv = bio->bi_io_vec + ci->idx;
 | 
							struct bio_vec *bv = bio->bi_io_vec + ci->idx;
 | 
				
			||||||
 | 
							sector_t remaining = to_sector(bv->bv_len);
 | 
				
			||||||
 | 
							unsigned int offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		clone = split_bvec(bio, ci->sector, ci->idx,
 | 
							do {
 | 
				
			||||||
				   bv->bv_offset, max);
 | 
								if (offset) {
 | 
				
			||||||
		__map_bio(ti, clone, tio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ci->sector += max;
 | 
					 | 
				
			||||||
		ci->sector_count -= max;
 | 
					 | 
				
			||||||
				ti = dm_table_find_target(ci->map, ci->sector);
 | 
									ti = dm_table_find_target(ci->map, ci->sector);
 | 
				
			||||||
 | 
									max = max_io_len(ci->md, ci->sector, ti);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		len = to_sector(bv->bv_len) - max;
 | 
					 | 
				
			||||||
		clone = split_bvec(bio, ci->sector, ci->idx,
 | 
					 | 
				
			||||||
				   bv->bv_offset + to_bytes(max), len);
 | 
					 | 
				
			||||||
				tio = alloc_tio(ci->md);
 | 
									tio = alloc_tio(ci->md);
 | 
				
			||||||
				tio->io = ci->io;
 | 
									tio->io = ci->io;
 | 
				
			||||||
				tio->ti = ti;
 | 
									tio->ti = ti;
 | 
				
			||||||
				memset(&tio->info, 0, sizeof(tio->info));
 | 
									memset(&tio->info, 0, sizeof(tio->info));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								len = min(remaining, max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								clone = split_bvec(bio, ci->sector, ci->idx,
 | 
				
			||||||
 | 
										   bv->bv_offset + offset, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			__map_bio(ti, clone, tio);
 | 
								__map_bio(ti, clone, tio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ci->sector += len;
 | 
								ci->sector += len;
 | 
				
			||||||
			ci->sector_count -= len;
 | 
								ci->sector_count -= len;
 | 
				
			||||||
 | 
								offset += to_bytes(len);
 | 
				
			||||||
 | 
							} while (remaining -= len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ci->idx++;
 | 
							ci->idx++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue