summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm.c22
-rw-r--r--include/linux/device-mapper.h15
2 files changed, 30 insertions, 7 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e417cf0a69ef..7e469260fe5e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1152,15 +1152,23 @@ static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti
{
struct bio *bio = ci->bio;
struct dm_target_io *tio;
+ unsigned target_bio_nr;
+ unsigned num_target_bios = 1;
- tio = alloc_tio(ci, ti, nr_iovecs, 0);
-
- if (split_bvec)
- clone_split_bio(tio, bio, sector, idx, offset, len);
- else
- clone_bio(tio, bio, sector, idx, bv_count, len);
+ /*
+ * Does the target want to receive duplicate copies of the bio?
+ */
+ if (bio_data_dir(bio) == WRITE && ti->num_write_bios)
+ num_target_bios = ti->num_write_bios(ti, bio);
- __map_bio(tio);
+ for (target_bio_nr = 0; target_bio_nr < num_target_bios; target_bio_nr++) {
+ tio = alloc_tio(ci, ti, nr_iovecs, target_bio_nr);
+ if (split_bvec)
+ clone_split_bio(tio, bio, sector, idx, offset, len);
+ else
+ clone_bio(tio, bio, sector, idx, bv_count, len);
+ __map_bio(tio);
+ }
}
typedef unsigned (*get_num_bios_fn)(struct dm_target *ti);
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index d5f984b07466..1e483fa7afb4 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -175,6 +175,14 @@ struct target_type {
#define DM_TARGET_IMMUTABLE 0x00000004
#define dm_target_is_immutable(type) ((type)->features & DM_TARGET_IMMUTABLE)
+/*
+ * Some targets need to be sent the same WRITE bio severals times so
+ * that they can send copies of it to different devices. This function
+ * examines any supplied bio and returns the number of copies of it the
+ * target requires.
+ */
+typedef unsigned (*dm_num_write_bios_fn) (struct dm_target *ti, struct bio *bio);
+
struct dm_target {
struct dm_table *table;
struct target_type *type;
@@ -214,6 +222,13 @@ struct dm_target {
*/
unsigned per_bio_data_size;
+ /*
+ * If defined, this function is called to find out how many
+ * duplicate bios should be sent to the target when writing
+ * data.
+ */
+ dm_num_write_bios_fn num_write_bios;
+
/* target specific data */
void *private;