diff options
author | Alasdair G Kergon <agk@redhat.com> | 2006-03-22 03:07:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-22 10:53:55 -0500 |
commit | d2044a94e80b61f68ee7456f82d9b443e9ff6ac7 (patch) | |
tree | 4488efc87514d440f5ca4b9fdca32dd173a04f63 | |
parent | 06f9d4f94a075285d25253edbf57f2cda07d4ff3 (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.c | 43 |
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 | } |