Skip to content

Commit

Permalink
dm: mark targets that pass integrity data
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
  • Loading branch information
Mikulas Patocka authored and snitm committed Apr 24, 2017
1 parent 3c12016 commit e2460f2
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 3 deletions.
1 change: 1 addition & 0 deletions drivers/md/dm-delay.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ static int delay_iterate_devices(struct dm_target *ti,
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,
Expand Down
1 change: 1 addition & 0 deletions drivers/md/dm-linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions drivers/md/dm-stripe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions drivers/md/dm-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 13 additions & 3 deletions drivers/md/dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1089,16 +1089,26 @@ 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;
}

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;
Expand Down
6 changes: 6 additions & 0 deletions include/linux/device-mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit e2460f2

Please sign in to comment.