Commit d2044a94 authored by Alasdair G Kergon's avatar Alasdair G Kergon Committed by Linus Torvalds

[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: default avatarAlasdair G Kergon <agk@redhat.com>
Cc: <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 06f9d4f9
...@@ -533,30 +533,35 @@ static void __clone_and_map(struct clone_info *ci) ...@@ -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++;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment