aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-delay.c1
-rw-r--r--drivers/md/dm-linear.c1
-rw-r--r--drivers/md/dm-stripe.c1
-rw-r--r--drivers/md/dm-table.c7
-rw-r--r--drivers/md/dm.c16
-rw-r--r--include/linux/device-mapper.h6
6 files changed, 29 insertions, 3 deletions
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index cc70871a6d29..ae3158795d26 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -340,6 +340,7 @@ out:
static struct target_type delay_target = {
.name = "delay",
.version = {1, 2, 1},
+ .features = DM_TARGET_PASSES_INTEGRITY,
.module = THIS_MODULE,
.ctr = delay_ctr,
.dtr = delay_dtr,
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 4788b0b989a9..ffa0c9c5968a 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -162,6 +162,7 @@ static long linear_direct_access(struct dm_target *ti, sector_t sector,
static struct target_type linear_target = {
.name = "linear",
.version = {1, 3, 0},
+ .features = DM_TARGET_PASSES_INTEGRITY,
.module = THIS_MODULE,
.ctr = linear_ctr,
.dtr = linear_dtr,
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 28193a57bf47..d7e1b86e7570 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -440,6 +440,7 @@ static void stripe_io_hints(struct dm_target *ti,
static struct target_type stripe_target = {
.name = "striped",
.version = {1, 6, 0},
+ .features = DM_TARGET_PASSES_INTEGRITY,
.module = THIS_MODULE,
.ctr = stripe_ctr,
.dtr = stripe_dtr,
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 7fb29db478cd..c68757f94e16 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1135,6 +1135,13 @@ static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t)
struct list_head *devices = dm_table_get_devices(t);
struct dm_dev_internal *dd = NULL;
struct gendisk *prev_disk = NULL, *template_disk = NULL;
+ unsigned i;
+
+ for (i = 0; i < dm_table_get_num_targets(t); i++) {
+ struct dm_target *ti = dm_table_get_target(t, i);
+ if (!dm_target_passes_integrity(ti->type))
+ goto no_integrity;
+ }
list_for_each_entry(dd, devices, list) {
template_disk = dd->dm_dev->bdev->bd_disk;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index f4ffd1eb8f44..e602ae0d5d75 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1089,8 +1089,18 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
__bio_clone_fast(clone, bio);
- if (bio_integrity(bio)) {
- int r = bio_integrity_clone(clone, bio, GFP_NOIO);
+ if (unlikely(bio_integrity(bio) != NULL)) {
+ int r;
+
+ if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
+ !dm_target_passes_integrity(tio->ti->type))) {
+ DMWARN("%s: the target %s doesn't support integrity data.",
+ dm_device_name(tio->io->md),
+ tio->ti->type->name);
+ return -EIO;
+ }
+
+ r = bio_integrity_clone(clone, bio, GFP_NOIO);
if (r < 0)
return r;
}
@@ -1098,7 +1108,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
clone->bi_iter.bi_size = to_bytes(len);
- if (bio_integrity(bio))
+ if (unlikely(bio_integrity(bio) != NULL))
bio_integrity_trim(clone, 0, len);
return 0;
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 874462153f14..98f981026e4e 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -227,6 +227,12 @@ typedef unsigned (*dm_num_write_bios_fn) (struct dm_target *ti, struct bio *bio)
#define DM_TARGET_INTEGRITY 0x00000010
#define dm_target_has_integrity(type) ((type)->features & DM_TARGET_INTEGRITY)
+/*
+ * A target passes integrity data to the lower device.
+ */
+#define DM_TARGET_PASSES_INTEGRITY 0x00000020
+#define dm_target_passes_integrity(type) ((type)->features & DM_TARGET_PASSES_INTEGRITY)
+
struct dm_target {
struct dm_table *table;
struct target_type *type;