aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2006-03-22 03:07:42 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-22 10:53:55 -0500
commitd2044a94e80b61f68ee7456f82d9b443e9ff6ac7 (patch)
tree4488efc87514d440f5ca4b9fdca32dd173a04f63
parent06f9d4f94a075285d25253edbf57f2cda07d4ff3 (diff)
[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>
-rw-r--r--drivers/md/dm.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 88d60202b9db..26b08ee425c7 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -533,30 +533,35 @@ static void __clone_and_map(struct clone_info *ci)
533 533
534 } else { 534 } else {
535 /* 535 /*
536 * Create two copy bios to deal with io that has 536 * Handle a bvec that must be split between two or more targets.
537 * been split across a target.
538 */ 537 */
539 struct bio_vec *bv = bio->bi_io_vec + ci->idx; 538 struct bio_vec *bv = bio->bi_io_vec + ci->idx;
539 sector_t remaining = to_sector(bv->bv_len);
540 unsigned int offset = 0;
540 541
541 clone = split_bvec(bio, ci->sector, ci->idx, 542 do {
542 bv->bv_offset, max); 543 if (offset) {
543 __map_bio(ti, clone, tio); 544 ti = dm_table_find_target(ci->map, ci->sector);
545 max = max_io_len(ci->md, ci->sector, ti);
544 546
545 ci->sector += max; 547 tio = alloc_tio(ci->md);
546 ci->sector_count -= max; 548 tio->io = ci->io;
547 ti = dm_table_find_target(ci->map, ci->sector); 549 tio->ti = ti;
548 550 memset(&tio->info, 0, sizeof(tio->info));
549 len = to_sector(bv->bv_len) - max; 551 }
550 clone = split_bvec(bio, ci->sector, ci->idx, 552
551 bv->bv_offset + to_bytes(max), len); 553 len = min(remaining, max);
552 tio = alloc_tio(ci->md); 554
553 tio->io = ci->io; 555 clone = split_bvec(bio, ci->sector, ci->idx,
554 tio->ti = ti; 556 bv->bv_offset + offset, len);
555 memset(&tio->info, 0, sizeof(tio->info)); 557
556 __map_bio(ti, clone, tio); 558 __map_bio(ti, clone, tio);
559
560 ci->sector += len;
561 ci->sector_count -= len;
562 offset += to_bytes(len);
563 } while (remaining -= len);
557 564
558 ci->sector += len;
559 ci->sector_count -= len;
560 ci->idx++; 565 ci->idx++;
561 } 566 }
562} 567}