Skip to content

Commit e2460f2

Browse files
Mikulas Patockasnitm
Mikulas Patocka
authored andcommitted
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>
1 parent 3c12016 commit e2460f2

File tree

6 files changed

+29
-3
lines changed

6 files changed

+29
-3
lines changed

drivers/md/dm-delay.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ static int delay_iterate_devices(struct dm_target *ti,
340340
static struct target_type delay_target = {
341341
.name = "delay",
342342
.version = {1, 2, 1},
343+
.features = DM_TARGET_PASSES_INTEGRITY,
343344
.module = THIS_MODULE,
344345
.ctr = delay_ctr,
345346
.dtr = delay_dtr,

drivers/md/dm-linear.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ static long linear_direct_access(struct dm_target *ti, sector_t sector,
162162
static struct target_type linear_target = {
163163
.name = "linear",
164164
.version = {1, 3, 0},
165+
.features = DM_TARGET_PASSES_INTEGRITY,
165166
.module = THIS_MODULE,
166167
.ctr = linear_ctr,
167168
.dtr = linear_dtr,

drivers/md/dm-stripe.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ static void stripe_io_hints(struct dm_target *ti,
440440
static struct target_type stripe_target = {
441441
.name = "striped",
442442
.version = {1, 6, 0},
443+
.features = DM_TARGET_PASSES_INTEGRITY,
443444
.module = THIS_MODULE,
444445
.ctr = stripe_ctr,
445446
.dtr = stripe_dtr,

drivers/md/dm-table.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,13 @@ static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t)
11351135
struct list_head *devices = dm_table_get_devices(t);
11361136
struct dm_dev_internal *dd = NULL;
11371137
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+
}
11381145

11391146
list_for_each_entry(dd, devices, list) {
11401147
template_disk = dd->dm_dev->bdev->bd_disk;

drivers/md/dm.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,16 +1089,26 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
10891089

10901090
__bio_clone_fast(clone, bio);
10911091

1092-
if (bio_integrity(bio)) {
1093-
int r = bio_integrity_clone(clone, bio, GFP_NOIO);
1092+
if (unlikely(bio_integrity(bio) != NULL)) {
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);
10941104
if (r < 0)
10951105
return r;
10961106
}
10971107

10981108
bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
10991109
clone->bi_iter.bi_size = to_bytes(len);
11001110

1101-
if (bio_integrity(bio))
1111+
if (unlikely(bio_integrity(bio) != NULL))
11021112
bio_integrity_trim(clone, 0, len);
11031113

11041114
return 0;

include/linux/device-mapper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ typedef unsigned (*dm_num_write_bios_fn) (struct dm_target *ti, struct bio *bio)
227227
#define DM_TARGET_INTEGRITY 0x00000010
228228
#define dm_target_has_integrity(type) ((type)->features & DM_TARGET_INTEGRITY)
229229

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+
230236
struct dm_target {
231237
struct dm_table *table;
232238
struct target_type *type;

0 commit comments

Comments
 (0)