aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2017-04-18 16:51:48 -0400
committerMike Snitzer <snitzer@redhat.com>2017-04-24 12:04:32 -0400
commite2460f2a4bc740fae9e23f14d653cf53e90b3f9a (patch)
tree61cf54345c7bca5844099f29abf0aa7da53135e8
parent3c12016910061c2a19d985fba7f7dec19d6a3a09 (diff)
dm: mark targets that pass integrity data
A dm-crypt on dm-integrity device incorrectly advertises an integrity profile on the DM crypt device. It can be seen in the files "/sys/block/dm-*/integrity/*" that both dm-integrity and dm-crypt target advertise the integrity profile. That is incorrect, only the dm-integrity target should advertise the integrity profile. A general problem in DM is that if we have a DM device that depends on another device with an integrity profile, the upper device will always advertise the integrity profile, even when the target driver doesn't support handling integrity data. Most targets don't support integrity data, so we provide a whitelist of targets that support it (linear, delay and striped). The targets that support passing integrity data to the lower device are marked with the flag DM_TARGET_PASSES_INTEGRITY. The DM core will now advertise integrity data on a DM device only if all the targets support the integrity data. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-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:
340static struct target_type delay_target = { 340static struct target_type delay_target = {
341 .name = "delay", 341 .name = "delay",
342 .version = {1, 2, 1}, 342 .version = {1, 2, 1},
343 .features = DM_TARGET_PASSES_INTEGRITY,
343 .module = THIS_MODULE, 344 .module = THIS_MODULE,
344 .ctr = delay_ctr, 345 .ctr = delay_ctr,
345 .dtr = delay_dtr, 346 .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,
162static struct target_type linear_target = { 162static struct target_type linear_target = {
163 .name = "linear", 163 .name = "linear",
164 .version = {1, 3, 0}, 164 .version = {1, 3, 0},
165 .features = DM_TARGET_PASSES_INTEGRITY,
165 .module = THIS_MODULE, 166 .module = THIS_MODULE,
166 .ctr = linear_ctr, 167 .ctr = linear_ctr,
167 .dtr = linear_dtr, 168 .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,
440static struct target_type stripe_target = { 440static struct target_type stripe_target = {
441 .name = "striped", 441 .name = "striped",
442 .version = {1, 6, 0}, 442 .version = {1, 6, 0},
443 .features = DM_TARGET_PASSES_INTEGRITY,
443 .module = THIS_MODULE, 444 .module = THIS_MODULE,
444 .ctr = stripe_ctr, 445 .ctr = stripe_ctr,
445 .dtr = stripe_dtr, 446 .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)
1135 struct list_head *devices = dm_table_get_devices(t); 1135 struct list_head *devices = dm_table_get_devices(t);
1136 struct dm_dev_internal *dd = NULL; 1136 struct dm_dev_internal *dd = NULL;
1137 struct gendisk *prev_disk = NULL, *template_disk = NULL; 1137 struct gendisk *prev_disk = NULL, *template_disk = NULL;
1138 unsigned i;
1139
1140 for (i = 0; i < dm_table_get_num_targets(t); i++) {
1141 struct dm_target *ti = dm_table_get_target(t, i);
1142 if (!dm_target_passes_integrity(ti->type))
1143 goto no_integrity;
1144 }
1138 1145
1139 list_for_each_entry(dd, devices, list) { 1146 list_for_each_entry(dd, devices, list) {
1140 template_disk = dd->dm_dev->bdev->bd_disk; 1147 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,
1089 1089
1090 __bio_clone_fast(clone, bio); 1090 __bio_clone_fast(clone, bio);
1091 1091
1092 if (bio_integrity(bio)) { 1092 if (unlikely(bio_integrity(bio) != NULL)) {
1093 int r = bio_integrity_clone(clone, bio, GFP_NOIO); 1093 int r;
1094
1095 if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
1096 !dm_target_passes_integrity(tio->ti->type))) {
1097 DMWARN("%s: the target %s doesn't support integrity data.",
1098 dm_device_name(tio->io->md),
1099 tio->ti->type->name);
1100 return -EIO;
1101 }
1102
1103 r = bio_integrity_clone(clone, bio, GFP_NOIO);
1094 if (r < 0) 1104 if (r < 0)
1095 return r; 1105 return r;
1096 } 1106 }
@@ -1098,7 +1108,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
1098 bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector)); 1108 bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
1099 clone->bi_iter.bi_size = to_bytes(len); 1109 clone->bi_iter.bi_size = to_bytes(len);
1100 1110
1101 if (bio_integrity(bio)) 1111 if (unlikely(bio_integrity(bio) != NULL))
1102 bio_integrity_trim(clone, 0, len); 1112 bio_integrity_trim(clone, 0, len);
1103 1113
1104 return 0; 1114 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)
227#define DM_TARGET_INTEGRITY 0x00000010 227#define DM_TARGET_INTEGRITY 0x00000010
228#define dm_target_has_integrity(type) ((type)->features & DM_TARGET_INTEGRITY) 228#define dm_target_has_integrity(type) ((type)->features & DM_TARGET_INTEGRITY)
229 229
230/*
231 * A target passes integrity data to the lower device.
232 */
233#define DM_TARGET_PASSES_INTEGRITY 0x00000020
234#define dm_target_passes_integrity(type) ((type)->features & DM_TARGET_PASSES_INTEGRITY)
235
230struct dm_target { 236struct dm_target {
231 struct dm_table *table; 237 struct dm_table *table;
232 struct target_type *type; 238 struct target_type *type;