From: Martin K. Petersen Add support for data integrity to DM. If all subdevices support the same protection format the DM device is flagged as capable. [FIXME: Doesn't yet cope with integrity profile needing removing after a table swap. blk_integrity_register() allocating & manipulating kobjects needs moving outside __bind().] Signed-off-by: Martin K. Petersen Signed-off-by: Alasdair G Kergon --- drivers/md/dm-table.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/md/dm.c | 15 +++++++++++++++ 2 files changed, 53 insertions(+) Index: linux-2.6.28-devel/drivers/md/dm-table.c =================================================================== --- linux-2.6.28-devel.orig/drivers/md/dm-table.c 2009-01-07 02:32:49.000000000 +0100 +++ linux-2.6.28-devel/drivers/md/dm-table.c 2009-01-07 02:32:56.000000000 +0100 @@ -864,6 +864,43 @@ struct dm_target *dm_table_find_target(s return &t->targets[(KEYS_PER_NODE * n) + k]; } +/* + * Set the integrity profile for this device if all devices used have + * matching profiles. + */ +static void dm_table_set_integrity(struct dm_table *t) +{ + struct list_head *devices = dm_table_get_devices(t); + struct dm_dev_internal *prev = NULL, *dd = NULL; + struct blk_integrity *bi; + + list_for_each_entry(dd, devices, list) { + if (prev && + blk_integrity_compare(prev->dm_dev.bdev->bd_disk, + dd->dm_dev.bdev->bd_disk) < 0) { + DMWARN("%s: integrity not set: %s and %s mismatch", + dm_device_name(t->md), + prev->dm_dev.bdev->bd_disk->disk_name, + dd->dm_dev.bdev->bd_disk->disk_name); + return; + } + prev = dd; + } + + if (!prev) + return; + + bi = bdev_get_integrity(prev->dm_dev.bdev); + if (!bi) + return; + + if (blk_integrity_register(dm_disk(t->md), bi)) + DMERR("%s: %s: blk_integrity_register failed.", + __func__, dm_device_name(t->md)); + else + DMDEBUG("%s: Enabling data integrity.", dm_device_name(t->md)); +} + void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) { /* @@ -884,6 +921,7 @@ void dm_table_set_restrictions(struct dm else queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); + dm_table_set_integrity(t); } unsigned int dm_table_get_num_targets(struct dm_table *t) Index: linux-2.6.28-devel/drivers/md/dm.c =================================================================== --- linux-2.6.28-devel.orig/drivers/md/dm.c 2009-01-07 02:32:49.000000000 +0100 +++ linux-2.6.28-devel/drivers/md/dm.c 2009-01-07 02:32:56.000000000 +0100 @@ -698,6 +698,12 @@ static struct bio *split_bvec(struct bio clone->bi_io_vec->bv_len = clone->bi_size; clone->bi_flags |= 1 << BIO_CLONED; + if (bio_integrity(bio)) { + bio_integrity_clone(clone, bio, bs); + bio_integrity_trim(clone, + bio_sector_offset(bio, idx, offset), len); + } + return clone; } @@ -719,6 +725,14 @@ static struct bio *clone_bio(struct bio clone->bi_size = to_bytes(len); clone->bi_flags &= ~(1 << BIO_SEG_VALID); + if (bio_integrity(bio)) { + bio_integrity_clone(clone, bio, bs); + + if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) + bio_integrity_trim(clone, + bio_sector_offset(bio, idx, 0), len); + } + return clone; } @@ -1191,6 +1205,7 @@ static void free_dev(struct mapped_devic mempool_destroy(md->tio_pool); mempool_destroy(md->io_pool); bioset_free(md->bs); + blk_integrity_unregister(md->disk); del_gendisk(md->disk); free_minor(minor);