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,
 
 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,
 
 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,
 
        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;
 
 
        __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;
        }
        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;
 
 #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;