From 90ce870cd60d0a255b4ed964920594c545ce472e Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 31 Mar 2011 15:19:05 -0400 Subject: [PATCH 5/5] dm_table_prealloc_integrity checking to verify that an initialized template matches the previously initailized DM device's integrity profile --- drivers/md/dm-table.c | 73 ++++++++++++++++++++++++++++++------------------- 1 files changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5ec729f..39ee315 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -932,31 +932,33 @@ static int dm_table_build_index(struct dm_table *t) * If %match_all is false, all devices must at least have an * allocated integrity profile; but uninitialized is ok. */ -static struct blk_integrity *dm_table_get_integrity(struct dm_table *t, bool match_all) +static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t, + bool match_all) { struct list_head *devices = dm_table_get_devices(t); - struct dm_dev_internal *prev = NULL, *dd = NULL; + struct dm_dev_internal *dd = NULL; + struct gendisk *prev_disk = NULL, *template_disk = NULL; struct blk_integrity *bi = NULL; list_for_each_entry(dd, devices, list) { - bi = bdev_get_integrity(dd->dm_dev.bdev); + template_disk = dd->dm_dev.bdev->bd_disk; + bi = blk_get_integrity(template_disk); if (!bi) goto no_integrity; if (!match_all && !blk_integrity_is_initialized(bi)) continue; /* skip uninitialized profiles */ - else if (prev && - blk_integrity_compare(prev->dm_dev.bdev->bd_disk, - dd->dm_dev.bdev->bd_disk) < 0) { + else if (prev_disk && + blk_integrity_compare(prev_disk, template_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); + prev_disk->disk_name, + template_disk->disk_name); goto no_integrity; } - prev = dd; + prev_disk = template_disk; } - return bi; + return template_disk; no_integrity: return NULL; @@ -974,25 +976,35 @@ no_integrity: */ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md) { - struct blk_integrity *bi = NULL; + struct gendisk *template_disk = NULL; + struct blk_integrity *template_bi = NULL, *dm_bi = NULL; - bi = dm_table_get_integrity(t, false); - if (bi) { + template_disk = dm_table_get_integrity_disk(t, false); + if (template_disk) { /* - * FIXME: if device already has an initalized integrity - * profile the new table's profile should not conflict. - * - return 'struct gendisk' from dm_table_get_integrity? - * - feed gendisk to existing blk_integrity_compare()? + * If DM device already has an initalized integrity + * profile the new profile should not conflict. */ + dm_bi = blk_get_integrity(dm_disk(md)); + template_bi = blk_get_integrity(template_disk); + if (blk_integrity_is_initialized(dm_bi)) { + if (blk_integrity_is_initialized(template_bi) && + blk_integrity_compare(dm_disk(md), template_disk) < 0) { + DMWARN("%s: existing integrity conflict: " + "%s mismatch", + dm_device_name(t->md), + template_disk->disk_name); + return 1; + } - t->integrity_supported = 1; - - /* - * Avoid clearing a previously established integrity profile - */ - if (blk_get_integrity(dm_disk(md))) + /* + * Avoid clearing an existing integrity profile + */ + t->integrity_supported = 1; return 0; + } + t->integrity_supported = 1; return blk_integrity_register(dm_disk(md), NULL); } @@ -1150,17 +1162,22 @@ combine_limits: /* * Set the integrity profile for this device if all devices used have * matching profiles. We're quite deep in the resume path but still - * don't know if all devices have matching profiles. - * FIXME: even if they didn't match we have no existing way to fail - * to resume at this point. + * don't know if all devices (particularly DM devices this device + * may be stacked on) have matching profiles. Even if the profiles + * don't match we have no way to fail (to resume) at this point. + * FIXME: should the integrity profile be cleared? */ static void dm_table_set_integrity(struct dm_table *t) { + struct gendisk *template_disk = NULL; + if (!blk_get_integrity(dm_disk(t->md))) return; - blk_integrity_register(dm_disk(t->md), - dm_table_get_integrity(t, true)); + template_disk = dm_table_get_integrity_disk(t, true); + if (template_disk) + blk_integrity_register(dm_disk(t->md), + blk_get_integrity(template_disk)); } void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, -- 1.7.3.4