mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
[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 {
|
||||
/*
|
||||
* Create two copy bios to deal with io that has
|
||||
* been split across a target.
|
||||
* Handle a bvec that must be split between two or more targets.
|
||||
*/
|
||||
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,
|
||||
bv->bv_offset, max);
|
||||
__map_bio(ti, clone, tio);
|
||||
do {
|
||||
if (offset) {
|
||||
ti = dm_table_find_target(ci->map, ci->sector);
|
||||
max = max_io_len(ci->md, ci->sector, ti);
|
||||
|
||||
ci->sector += max;
|
||||
ci->sector_count -= max;
|
||||
ti = dm_table_find_target(ci->map, ci->sector);
|
||||
tio = alloc_tio(ci->md);
|
||||
tio->io = ci->io;
|
||||
tio->ti = ti;
|
||||
memset(&tio->info, 0, sizeof(tio->info));
|
||||
}
|
||||
|
||||
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->io = ci->io;
|
||||
tio->ti = ti;
|
||||
memset(&tio->info, 0, sizeof(tio->info));
|
||||
__map_bio(ti, clone, tio);
|
||||
len = min(remaining, max);
|
||||
|
||||
clone = split_bvec(bio, ci->sector, ci->idx,
|
||||
bv->bv_offset + offset, len);
|
||||
|
||||
__map_bio(ti, clone, tio);
|
||||
|
||||
ci->sector += len;
|
||||
ci->sector_count -= len;
|
||||
offset += to_bytes(len);
|
||||
} while (remaining -= len);
|
||||
|
||||
ci->sector += len;
|
||||
ci->sector_count -= len;
|
||||
ci->idx++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue