diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/bitmap.h | 2 | ||||
-rw-r--r-- | drivers/md/dm-region-hash.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 114 | ||||
-rw-r--r-- | drivers/md/faulty.c | 2 | ||||
-rw-r--r-- | drivers/md/md.c | 2 | ||||
-rw-r--r-- | drivers/md/md.h | 2 | ||||
-rw-r--r-- | drivers/md/raid10.c | 6 | ||||
-rw-r--r-- | drivers/md/raid10.h | 4 |
8 files changed, 90 insertions, 44 deletions
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index 931a7a7..d0aeaf4 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -45,7 +45,7 @@ * * The counter counts pending write requests, plus the on-disk bit. * When the counter is '1' and the resync bits are clear, the on-disk - * bit can be cleared aswell, thus setting the counter to 0. + * bit can be cleared as well, thus setting the counter to 0. * When we set a bit, or in the counter (to start a write), if the fields is * 0, we first set the disk bit and set the counter to 1. * diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index dad011a..7771ed2 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -419,7 +419,7 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio) /* * Possible cases: * 1) DM_RH_DIRTY - * 2) DM_RH_NOSYNC: was dirty, other preceeding writes failed + * 2) DM_RH_NOSYNC: was dirty, other preceding writes failed * 3) DM_RH_RECOVERING: flushing pending writes * Either case, the region should have not been connected to list. */ diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 416d4e2..cb8380c 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -927,20 +927,80 @@ static int dm_table_build_index(struct dm_table *t) } /* + * Get a disk whose integrity profile reflects the table's profile. + * If %match_all is true, all devices' profiles must match. + * If %match_all is false, all devices must at least have an + * allocated integrity profile; but uninitialized is ok. + * Returns NULL if integrity support was inconsistent or unavailable. + */ +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 *dd = NULL; + struct gendisk *prev_disk = NULL, *template_disk = NULL; + + list_for_each_entry(dd, devices, list) { + template_disk = dd->dm_dev.bdev->bd_disk; + if (!blk_get_integrity(template_disk)) + goto no_integrity; + if (!match_all && !blk_integrity_is_initialized(template_disk)) + continue; /* skip uninitialized profiles */ + else if (prev_disk && + blk_integrity_compare(prev_disk, template_disk) < 0) + goto no_integrity; + prev_disk = template_disk; + } + + return template_disk; + +no_integrity: + if (prev_disk) + DMWARN("%s: integrity not set: %s and %s profile mismatch", + dm_device_name(t->md), + prev_disk->disk_name, + template_disk->disk_name); + 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 gendisk *template_disk = 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); - } + template_disk = dm_table_get_integrity_disk(t, false); + if (!template_disk) + return 0; + if (!blk_integrity_is_initialized(dm_disk(md))) { + t->integrity_supported = 1; + return blk_integrity_register(dm_disk(md), NULL); + } + + /* + * If DM device already has an initalized integrity + * profile the new profile should not conflict. + */ + if (blk_integrity_is_initialized(template_disk) && + blk_integrity_compare(dm_disk(md), template_disk) < 0) { + DMWARN("%s: conflict with existing integrity profile: " + "%s profile mismatch", + dm_device_name(t->md), + template_disk->disk_name); + return 1; + } + + /* Preserve existing initialized integrity profile */ + t->integrity_supported = 1; return 0; } @@ -1094,41 +1154,27 @@ 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 (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. */ 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 gendisk *template_disk = 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; + template_disk = dm_table_get_integrity_disk(t, true); + if (!template_disk && + blk_integrity_is_initialized(dm_disk(t->md))) { + DMWARN("%s: device no longer has a valid integrity profile", + dm_device_name(t->md)); + return; } - - 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; + blk_get_integrity(template_disk)); } void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 339fdc6..23078da 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -30,7 +30,7 @@ * * Different modes can be active at a time, but only * one can be set at array creation. Others can be added later. - * A mode can be one-shot or recurrent with the recurrance being + * A mode can be one-shot or recurrent with the recurrence being * once in every N requests. * The bottom 5 bits of the "layout" indicate the mode. The * remainder indicate a period, or 0 for one-shot. diff --git a/drivers/md/md.c b/drivers/md/md.c index 8b66e04..b12b377 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6266,7 +6266,7 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) * rt is a sector_t, so could be 32bit or 64bit. * So we divide before multiply in case it is 32bit and close * to the limit. - * We scale the divisor (db) by 32 to avoid loosing precision + * We scale the divisor (db) by 32 to avoid losing precision * near the end of resync when the number of remaining sectors * is close to 'db'. * We then divide rt by 32 after multiplying by db to compensate. diff --git a/drivers/md/md.h b/drivers/md/md.h index 12215d4..52b4073 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -94,7 +94,7 @@ struct mdk_rdev_s #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ #define AutoDetected 7 /* added by auto-detect */ -#define Blocked 8 /* An error occured on an externally +#define Blocked 8 /* An error occurred on an externally * managed array, don't allow writes * until it is cleared */ wait_queue_head_t blocked_wait; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f7b6237..2da83d5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -5,7 +5,7 @@ * * RAID-10 support for md. * - * Base on code in raid1.c. See raid1.c for futher copyright information. + * Base on code in raid1.c. See raid1.c for further copyright information. * * * This program is free software; you can redistribute it and/or modify @@ -340,14 +340,14 @@ static void raid10_end_write_request(struct bio *bio, int error) /* * RAID10 layout manager - * Aswell as the chunksize and raid_disks count, there are two + * As well as the chunksize and raid_disks count, there are two * parameters: near_copies and far_copies. * near_copies * far_copies must be <= raid_disks. * Normally one of these will be 1. * If both are 1, we get raid0. * If near_copies == raid_disks, we get raid1. * - * Chunks are layed out in raid0 style with near_copies copies of the + * Chunks are laid out in raid0 style with near_copies copies of the * first chunk, followed by near_copies copies of the next chunk and * so on. * If far_copies > 1, then after 1/far_copies of the array has been assigned diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 2316ac2..944b110 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -17,8 +17,8 @@ struct r10_private_data_s { spinlock_t device_lock; /* geometry */ - int near_copies; /* number of copies layed out raid0 style */ - int far_copies; /* number of copies layed out + int near_copies; /* number of copies laid out raid0 style */ + int far_copies; /* number of copies laid out * at large strides across drives */ int far_offset; /* far_copies are offset by 1 stripe |