|
@@ -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
|
|
|
|
- * 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;
|
|
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);
|
|
|
|
-
|
|
|
|
- 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);
|
|
|
|
|
|
+ tio = alloc_tio(ci->md);
|
|
|
|
+ tio->io = ci->io;
|
|
|
|
+ tio->ti = ti;
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ ci->sector += len;
|
|
|
|
+ ci->sector_count -= len;
|
|
|
|
+ offset += to_bytes(len);
|
|
|
|
+ } while (remaining -= len);
|
|
|
|
|
|
- ci->sector += len;
|
|
|
|
- ci->sector_count -= len;
|
|
|
|
ci->idx++;
|
|
ci->idx++;
|
|
}
|
|
}
|
|
}
|
|
}
|