From 70266e0c1432f33754bd807f0e104f1541888403 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Wed, 30 Mar 2011 21:55:51 -0400 Subject: [PATCH 1/5] initial refactor of DM integrity support --- drivers/md/dm-table.c | 102 +++++++++++++++++++++++++++++++----------------- 1 files changed, 66 insertions(+), 36 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 416d4e2..f3f70d6 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -927,19 +927,72 @@ static int dm_table_build_index(struct dm_table *t) } /* + * Get the integrity profile for the table. + * If %compare is true, all devices' profiles must match. + * If %compare is false, all devices must at least have an + * allocated integrity profile. + * FIXME: add a new integrity method: blk_integrity_initialized() to + * skip comparisons with uninitialized profiles during table load. + */ +static struct blk_integrity *dm_table_get_integrity(struct dm_table *t, bool compare) +{ + struct list_head *devices = dm_table_get_devices(t); + struct dm_dev_internal *prev = NULL, *dd = NULL; + + list_for_each_entry(dd, devices, list) { + if (compare && 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); + goto no_integrity; + } else if (!bdev_get_integrity(dd->dm_dev.bdev)) + goto no_integrity; + prev = dd; + } + + if (prev) + return bdev_get_integrity(prev->dm_dev.bdev); + +no_integrity: + return NULL; +} + +/* * Register the mapped device for blk_integrity support if - * the underlying devices support it. + * the underlying devices have an integrity profile. But all devices + * may not have matching profiles (checking all devices isn't reliable + * during table load because this table may use other DM device(s) which + * must be resumed before they will have an initialized integity profile). + * Stacked DM devices force a 2 stage integrity profile validation: + * 1 - during load, validate all initialized integrity profiles match + * 2 - during resume, validate all integrity profiles match */ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md) { - struct list_head *devices = dm_table_get_devices(t); - struct dm_dev_internal *dd; + struct blk_integrity *bi = NULL; - list_for_each_entry(dd, devices, list) - if (bdev_get_integrity(dd->dm_dev.bdev)) { - t->integrity_supported = 1; - return blk_integrity_register(dm_disk(md), NULL); - } + bi = dm_table_get_integrity(t, false); + if (bi) { + /* + * 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()? + */ + + t->integrity_supported = 1; + + /* + * Avoid clearing a previously established integrity profile + */ + if (bdev_get_integrity(dm_disk(md))) + return 0; + + return blk_integrity_register(dm_disk(md), NULL); + } return 0; } @@ -1094,41 +1147,18 @@ combine_limits: /* * Set the integrity profile for this device if all devices used have - * matching profiles. + * 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. */ 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; - if (!blk_get_integrity(dm_disk(t->md))) return; - 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); - goto no_integrity; - } - prev = dd; - } - - if (!prev || !bdev_get_integrity(prev->dm_dev.bdev)) - goto no_integrity; - blk_integrity_register(dm_disk(t->md), - bdev_get_integrity(prev->dm_dev.bdev)); - - return; - -no_integrity: - blk_integrity_register(dm_disk(t->md), NULL); - - return; + dm_table_get_integrity(t, true)); } void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, -- 1.7.3.4