aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2015-10-21 13:19:49 -0400
committerJens Axboe <axboe@fb.com>2015-10-21 16:42:42 -0400
commit25520d55cdb6ee289abc68f553d364d22478ff54 (patch)
tree84e447f762e7f60095d0c4d24fdf2d9440f4b06d
parent4c241d08dbfcbdc7a949b91d72707a289d464954 (diff)
block: Inline blk_integrity in struct gendisk
Up until now the_integrity profile has been dynamically allocated and attached to struct gendisk after the disk has been made active. This causes problems because NVMe devices need to register the profile prior to the partition table being read due to a mandatory metadata buffer requirement. In addition, DM goes through hoops to deal with preallocating, but not initializing integrity profiles. Since the integrity profile is small (4 bytes + a pointer), Christoph suggested moving it to struct gendisk proper. This requires several changes: - Moving the blk_integrity definition to genhd.h. - Inlining blk_integrity in struct gendisk. - Removing the dynamic allocation code. - Adding helper functions which allow gendisk to set up and tear down the integrity sysfs dir when a disk is added/deleted. - Adding a blk_integrity_revalidate() callback for updating the stable pages bdi setting. - The calls that depend on whether a device has an integrity profile or not now key off of the bi->profile pointer. - Simplifying the integrity support routines in DM (Mike Snitzer). Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Reported-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Cc: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-integrity.c160
-rw-r--r--block/genhd.c2
-rw-r--r--block/partition-generic.c1
-rw-r--r--drivers/md/dm-table.c88
-rw-r--r--drivers/md/md.c9
-rw-r--r--drivers/nvdimm/core.c6
-rw-r--r--drivers/nvme/host/pci.c5
-rw-r--r--fs/block_dev.c2
-rw-r--r--include/linux/blkdev.h34
-rw-r--r--include/linux/genhd.h26
10 files changed, 152 insertions, 181 deletions
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 7a96f57ed195..4615a3386798 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -30,10 +30,6 @@
30 30
31#include "blk.h" 31#include "blk.h"
32 32
33static struct kmem_cache *integrity_cachep;
34
35static const char *bi_unsupported_name = "unsupported";
36
37/** 33/**
38 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements 34 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
39 * @q: request queue 35 * @q: request queue
@@ -146,13 +142,13 @@ EXPORT_SYMBOL(blk_rq_map_integrity_sg);
146 */ 142 */
147int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) 143int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
148{ 144{
149 struct blk_integrity *b1 = gd1->integrity; 145 struct blk_integrity *b1 = &gd1->integrity;
150 struct blk_integrity *b2 = gd2->integrity; 146 struct blk_integrity *b2 = &gd2->integrity;
151 147
152 if (!b1 && !b2) 148 if (!b1->profile && !b2->profile)
153 return 0; 149 return 0;
154 150
155 if (!b1 || !b2) 151 if (!b1->profile || !b2->profile)
156 return -1; 152 return -1;
157 153
158 if (b1->interval_exp != b2->interval_exp) { 154 if (b1->interval_exp != b2->interval_exp) {
@@ -163,21 +159,21 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
163 } 159 }
164 160
165 if (b1->tuple_size != b2->tuple_size) { 161 if (b1->tuple_size != b2->tuple_size) {
166 printk(KERN_ERR "%s: %s/%s tuple sz %u != %u\n", __func__, 162 pr_err("%s: %s/%s tuple sz %u != %u\n", __func__,
167 gd1->disk_name, gd2->disk_name, 163 gd1->disk_name, gd2->disk_name,
168 b1->tuple_size, b2->tuple_size); 164 b1->tuple_size, b2->tuple_size);
169 return -1; 165 return -1;
170 } 166 }
171 167
172 if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { 168 if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) {
173 printk(KERN_ERR "%s: %s/%s tag sz %u != %u\n", __func__, 169 pr_err("%s: %s/%s tag sz %u != %u\n", __func__,
174 gd1->disk_name, gd2->disk_name, 170 gd1->disk_name, gd2->disk_name,
175 b1->tag_size, b2->tag_size); 171 b1->tag_size, b2->tag_size);
176 return -1; 172 return -1;
177 } 173 }
178 174
179 if (b1->profile != b2->profile) { 175 if (b1->profile != b2->profile) {
180 printk(KERN_ERR "%s: %s/%s type %s != %s\n", __func__, 176 pr_err("%s: %s/%s type %s != %s\n", __func__,
181 gd1->disk_name, gd2->disk_name, 177 gd1->disk_name, gd2->disk_name,
182 b1->profile->name, b2->profile->name); 178 b1->profile->name, b2->profile->name);
183 return -1; 179 return -1;
@@ -250,7 +246,7 @@ static ssize_t integrity_attr_show(struct kobject *kobj, struct attribute *attr,
250 char *page) 246 char *page)
251{ 247{
252 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj); 248 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj);
253 struct blk_integrity *bi = blk_get_integrity(disk); 249 struct blk_integrity *bi = &disk->integrity;
254 struct integrity_sysfs_entry *entry = 250 struct integrity_sysfs_entry *entry =
255 container_of(attr, struct integrity_sysfs_entry, attr); 251 container_of(attr, struct integrity_sysfs_entry, attr);
256 252
@@ -262,7 +258,7 @@ static ssize_t integrity_attr_store(struct kobject *kobj,
262 size_t count) 258 size_t count)
263{ 259{
264 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj); 260 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj);
265 struct blk_integrity *bi = blk_get_integrity(disk); 261 struct blk_integrity *bi = &disk->integrity;
266 struct integrity_sysfs_entry *entry = 262 struct integrity_sysfs_entry *entry =
267 container_of(attr, struct integrity_sysfs_entry, attr); 263 container_of(attr, struct integrity_sysfs_entry, attr);
268 ssize_t ret = 0; 264 ssize_t ret = 0;
@@ -275,7 +271,7 @@ static ssize_t integrity_attr_store(struct kobject *kobj,
275 271
276static ssize_t integrity_format_show(struct blk_integrity *bi, char *page) 272static ssize_t integrity_format_show(struct blk_integrity *bi, char *page)
277{ 273{
278 if (bi != NULL && bi->profile->name != NULL) 274 if (bi->profile && bi->profile->name)
279 return sprintf(page, "%s\n", bi->profile->name); 275 return sprintf(page, "%s\n", bi->profile->name);
280 else 276 else
281 return sprintf(page, "none\n"); 277 return sprintf(page, "none\n");
@@ -283,18 +279,13 @@ static ssize_t integrity_format_show(struct blk_integrity *bi, char *page)
283 279
284static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page) 280static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page)
285{ 281{
286 if (bi != NULL) 282 return sprintf(page, "%u\n", bi->tag_size);
287 return sprintf(page, "%u\n", bi->tag_size);
288 else
289 return sprintf(page, "0\n");
290} 283}
291 284
292static ssize_t integrity_interval_show(struct blk_integrity *bi, char *page) 285static ssize_t integrity_interval_show(struct blk_integrity *bi, char *page)
293{ 286{
294 if (bi != NULL) 287 return sprintf(page, "%u\n",
295 return sprintf(page, "%u\n", 1 << bi->interval_exp); 288 bi->interval_exp ? 1 << bi->interval_exp : 0);
296 else
297 return sprintf(page, "0\n");
298} 289}
299 290
300static ssize_t integrity_verify_store(struct blk_integrity *bi, 291static ssize_t integrity_verify_store(struct blk_integrity *bi,
@@ -388,113 +379,78 @@ static const struct sysfs_ops integrity_ops = {
388 .store = &integrity_attr_store, 379 .store = &integrity_attr_store,
389}; 380};
390 381
391static int __init blk_dev_integrity_init(void)
392{
393 integrity_cachep = kmem_cache_create("blkdev_integrity",
394 sizeof(struct blk_integrity),
395 0, SLAB_PANIC, NULL);
396 return 0;
397}
398subsys_initcall(blk_dev_integrity_init);
399
400static void blk_integrity_release(struct kobject *kobj)
401{
402 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj);
403 struct blk_integrity *bi = blk_get_integrity(disk);
404
405 kmem_cache_free(integrity_cachep, bi);
406}
407
408static struct kobj_type integrity_ktype = { 382static struct kobj_type integrity_ktype = {
409 .default_attrs = integrity_attrs, 383 .default_attrs = integrity_attrs,
410 .sysfs_ops = &integrity_ops, 384 .sysfs_ops = &integrity_ops,
411 .release = blk_integrity_release,
412}; 385};
413 386
414bool blk_integrity_is_initialized(struct gendisk *disk)
415{
416 struct blk_integrity *bi = blk_get_integrity(disk);
417
418 return (bi && bi->profile->name && strcmp(bi->profile->name,
419 bi_unsupported_name) != 0);
420}
421EXPORT_SYMBOL(blk_integrity_is_initialized);
422
423/** 387/**
424 * blk_integrity_register - Register a gendisk as being integrity-capable 388 * blk_integrity_register - Register a gendisk as being integrity-capable
425 * @disk: struct gendisk pointer to make integrity-aware 389 * @disk: struct gendisk pointer to make integrity-aware
426 * @template: optional integrity profile to register 390 * @template: block integrity profile to register
427 * 391 *
428 * Description: When a device needs to advertise itself as being able 392 * Description: When a device needs to advertise itself as being able to
429 * to send/receive integrity metadata it must use this function to 393 * send/receive integrity metadata it must use this function to register
430 * register the capability with the block layer. The template is a 394 * the capability with the block layer. The template is a blk_integrity
431 * blk_integrity struct with values appropriate for the underlying 395 * struct with values appropriate for the underlying hardware. See
432 * hardware. If template is NULL the new profile is allocated but 396 * Documentation/block/data-integrity.txt.
433 * not filled out. See Documentation/block/data-integrity.txt.
434 */ 397 */
435int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) 398void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
436{ 399{
437 struct blk_integrity *bi; 400 struct blk_integrity *bi = &disk->integrity;
438
439 BUG_ON(disk == NULL);
440 401
441 if (disk->integrity == NULL) { 402 bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
442 bi = kmem_cache_alloc(integrity_cachep, 403 template->flags;
443 GFP_KERNEL | __GFP_ZERO); 404 bi->interval_exp = ilog2(queue_logical_block_size(disk->queue));
444 if (!bi) 405 bi->profile = template->profile;
445 return -1; 406 bi->tuple_size = template->tuple_size;
407 bi->tag_size = template->tag_size;
446 408
447 if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype, 409 blk_integrity_revalidate(disk);
448 &disk_to_dev(disk)->kobj,
449 "%s", "integrity")) {
450 kmem_cache_free(integrity_cachep, bi);
451 return -1;
452 }
453
454 kobject_uevent(&disk->integrity_kobj, KOBJ_ADD);
455
456 bi->flags |= BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE;
457 bi->interval_exp = ilog2(queue_logical_block_size(disk->queue));
458 disk->integrity = bi;
459 } else
460 bi = disk->integrity;
461
462 /* Use the provided profile as template */
463 if (template != NULL) {
464 bi->profile = template->profile;
465 bi->tuple_size = template->tuple_size;
466 bi->tag_size = template->tag_size;
467 bi->flags |= template->flags;
468 } else
469 bi->profile->name = bi_unsupported_name;
470
471 disk->queue->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
472
473 return 0;
474} 410}
475EXPORT_SYMBOL(blk_integrity_register); 411EXPORT_SYMBOL(blk_integrity_register);
476 412
477/** 413/**
478 * blk_integrity_unregister - Remove block integrity profile 414 * blk_integrity_unregister - Unregister block integrity profile
479 * @disk: disk whose integrity profile to deallocate 415 * @disk: disk whose integrity profile to unregister
480 * 416 *
481 * Description: This function frees all memory used by the block 417 * Description: This function unregisters the integrity capability from
482 * integrity profile. To be called at device teardown. 418 * a block device.
483 */ 419 */
484void blk_integrity_unregister(struct gendisk *disk) 420void blk_integrity_unregister(struct gendisk *disk)
485{ 421{
486 struct blk_integrity *bi; 422 blk_integrity_revalidate(disk);
423 memset(&disk->integrity, 0, sizeof(struct blk_integrity));
424}
425EXPORT_SYMBOL(blk_integrity_unregister);
487 426
488 if (!disk || !disk->integrity) 427void blk_integrity_revalidate(struct gendisk *disk)
428{
429 struct blk_integrity *bi = &disk->integrity;
430
431 if (!(disk->flags & GENHD_FL_UP))
489 return; 432 return;
490 433
491 disk->queue->backing_dev_info.capabilities &= ~BDI_CAP_STABLE_WRITES; 434 if (bi->profile)
435 disk->queue->backing_dev_info.capabilities |=
436 BDI_CAP_STABLE_WRITES;
437 else
438 disk->queue->backing_dev_info.capabilities &=
439 ~BDI_CAP_STABLE_WRITES;
440}
492 441
493 bi = disk->integrity; 442void blk_integrity_add(struct gendisk *disk)
443{
444 if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype,
445 &disk_to_dev(disk)->kobj, "%s", "integrity"))
446 return;
494 447
448 kobject_uevent(&disk->integrity_kobj, KOBJ_ADD);
449}
450
451void blk_integrity_del(struct gendisk *disk)
452{
495 kobject_uevent(&disk->integrity_kobj, KOBJ_REMOVE); 453 kobject_uevent(&disk->integrity_kobj, KOBJ_REMOVE);
496 kobject_del(&disk->integrity_kobj); 454 kobject_del(&disk->integrity_kobj);
497 kobject_put(&disk->integrity_kobj); 455 kobject_put(&disk->integrity_kobj);
498 disk->integrity = NULL;
499} 456}
500EXPORT_SYMBOL(blk_integrity_unregister);
diff --git a/block/genhd.c b/block/genhd.c
index 0c706f33a599..e5cafa51567c 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -630,6 +630,7 @@ void add_disk(struct gendisk *disk)
630 WARN_ON(retval); 630 WARN_ON(retval);
631 631
632 disk_add_events(disk); 632 disk_add_events(disk);
633 blk_integrity_add(disk);
633} 634}
634EXPORT_SYMBOL(add_disk); 635EXPORT_SYMBOL(add_disk);
635 636
@@ -638,6 +639,7 @@ void del_gendisk(struct gendisk *disk)
638 struct disk_part_iter piter; 639 struct disk_part_iter piter;
639 struct hd_struct *part; 640 struct hd_struct *part;
640 641
642 blk_integrity_del(disk);
641 disk_del_events(disk); 643 disk_del_events(disk);
642 644
643 /* invalidate stuff */ 645 /* invalidate stuff */
diff --git a/block/partition-generic.c b/block/partition-generic.c
index e7711133284e..3b030157ec85 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -428,6 +428,7 @@ rescan:
428 428
429 if (disk->fops->revalidate_disk) 429 if (disk->fops->revalidate_disk)
430 disk->fops->revalidate_disk(disk); 430 disk->fops->revalidate_disk(disk);
431 blk_integrity_revalidate(disk);
431 check_disk_size_change(disk, bdev); 432 check_disk_size_change(disk, bdev);
432 bdev->bd_invalidated = 0; 433 bdev->bd_invalidated = 0;
433 if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) 434 if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index e76ed003769e..061152a43730 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1014,15 +1014,16 @@ static int dm_table_build_index(struct dm_table *t)
1014 return r; 1014 return r;
1015} 1015}
1016 1016
1017static bool integrity_profile_exists(struct gendisk *disk)
1018{
1019 return !!blk_get_integrity(disk);
1020}
1021
1017/* 1022/*
1018 * Get a disk whose integrity profile reflects the table's profile. 1023 * Get a disk whose integrity profile reflects the table's profile.
1019 * If %match_all is true, all devices' profiles must match.
1020 * If %match_all is false, all devices must at least have an
1021 * allocated integrity profile; but uninitialized is ok.
1022 * Returns NULL if integrity support was inconsistent or unavailable. 1024 * Returns NULL if integrity support was inconsistent or unavailable.
1023 */ 1025 */
1024static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t, 1026static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t)
1025 bool match_all)
1026{ 1027{
1027 struct list_head *devices = dm_table_get_devices(t); 1028 struct list_head *devices = dm_table_get_devices(t);
1028 struct dm_dev_internal *dd = NULL; 1029 struct dm_dev_internal *dd = NULL;
@@ -1030,10 +1031,8 @@ static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
1030 1031
1031 list_for_each_entry(dd, devices, list) { 1032 list_for_each_entry(dd, devices, list) {
1032 template_disk = dd->dm_dev->bdev->bd_disk; 1033 template_disk = dd->dm_dev->bdev->bd_disk;
1033 if (!blk_get_integrity(template_disk)) 1034 if (!integrity_profile_exists(template_disk))
1034 goto no_integrity; 1035 goto no_integrity;
1035 if (!match_all && !blk_integrity_is_initialized(template_disk))
1036 continue; /* skip uninitialized profiles */
1037 else if (prev_disk && 1036 else if (prev_disk &&
1038 blk_integrity_compare(prev_disk, template_disk) < 0) 1037 blk_integrity_compare(prev_disk, template_disk) < 0)
1039 goto no_integrity; 1038 goto no_integrity;
@@ -1052,34 +1051,40 @@ no_integrity:
1052} 1051}
1053 1052
1054/* 1053/*
1055 * Register the mapped device for blk_integrity support if 1054 * Register the mapped device for blk_integrity support if the
1056 * the underlying devices have an integrity profile. But all devices 1055 * underlying devices have an integrity profile. But all devices may
1057 * may not have matching profiles (checking all devices isn't reliable 1056 * not have matching profiles (checking all devices isn't reliable
1058 * during table load because this table may use other DM device(s) which 1057 * during table load because this table may use other DM device(s) which
1059 * must be resumed before they will have an initialized integity profile). 1058 * must be resumed before they will have an initialized integity
1060 * Stacked DM devices force a 2 stage integrity profile validation: 1059 * profile). Consequently, stacked DM devices force a 2 stage integrity
1061 * 1 - during load, validate all initialized integrity profiles match 1060 * profile validation: First pass during table load, final pass during
1062 * 2 - during resume, validate all integrity profiles match 1061 * resume.
1063 */ 1062 */
1064static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md) 1063static int dm_table_register_integrity(struct dm_table *t)
1065{ 1064{
1065 struct mapped_device *md = t->md;
1066 struct gendisk *template_disk = NULL; 1066 struct gendisk *template_disk = NULL;
1067 1067
1068 template_disk = dm_table_get_integrity_disk(t, false); 1068 template_disk = dm_table_get_integrity_disk(t);
1069 if (!template_disk) 1069 if (!template_disk)
1070 return 0; 1070 return 0;
1071 1071
1072 if (!blk_integrity_is_initialized(dm_disk(md))) { 1072 if (!integrity_profile_exists(dm_disk(md))) {
1073 t->integrity_supported = 1; 1073 t->integrity_supported = 1;
1074 return blk_integrity_register(dm_disk(md), NULL); 1074 /*
1075 * Register integrity profile during table load; we can do
1076 * this because the final profile must match during resume.
1077 */
1078 blk_integrity_register(dm_disk(md),
1079 blk_get_integrity(template_disk));
1080 return 0;
1075 } 1081 }
1076 1082
1077 /* 1083 /*
1078 * If DM device already has an initalized integrity 1084 * If DM device already has an initialized integrity
1079 * profile the new profile should not conflict. 1085 * profile the new profile should not conflict.
1080 */ 1086 */
1081 if (blk_integrity_is_initialized(template_disk) && 1087 if (blk_integrity_compare(dm_disk(md), template_disk) < 0) {
1082 blk_integrity_compare(dm_disk(md), template_disk) < 0) {
1083 DMWARN("%s: conflict with existing integrity profile: " 1088 DMWARN("%s: conflict with existing integrity profile: "
1084 "%s profile mismatch", 1089 "%s profile mismatch",
1085 dm_device_name(t->md), 1090 dm_device_name(t->md),
@@ -1087,7 +1092,7 @@ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device
1087 return 1; 1092 return 1;
1088 } 1093 }
1089 1094
1090 /* Preserve existing initialized integrity profile */ 1095 /* Preserve existing integrity profile */
1091 t->integrity_supported = 1; 1096 t->integrity_supported = 1;
1092 return 0; 1097 return 0;
1093} 1098}
@@ -1112,7 +1117,7 @@ int dm_table_complete(struct dm_table *t)
1112 return r; 1117 return r;
1113 } 1118 }
1114 1119
1115 r = dm_table_prealloc_integrity(t, t->md); 1120 r = dm_table_register_integrity(t);
1116 if (r) { 1121 if (r) {
1117 DMERR("could not register integrity profile."); 1122 DMERR("could not register integrity profile.");
1118 return r; 1123 return r;
@@ -1278,29 +1283,30 @@ combine_limits:
1278} 1283}
1279 1284
1280/* 1285/*
1281 * Set the integrity profile for this device if all devices used have 1286 * Verify that all devices have an integrity profile that matches the
1282 * matching profiles. We're quite deep in the resume path but still 1287 * DM device's registered integrity profile. If the profiles don't
1283 * don't know if all devices (particularly DM devices this device 1288 * match then unregister the DM device's integrity profile.
1284 * may be stacked on) have matching profiles. Even if the profiles
1285 * don't match we have no way to fail (to resume) at this point.
1286 */ 1289 */
1287static void dm_table_set_integrity(struct dm_table *t) 1290static void dm_table_verify_integrity(struct dm_table *t)
1288{ 1291{
1289 struct gendisk *template_disk = NULL; 1292 struct gendisk *template_disk = NULL;
1290 1293
1291 if (!blk_get_integrity(dm_disk(t->md))) 1294 if (t->integrity_supported) {
1292 return; 1295 /*
1296 * Verify that the original integrity profile
1297 * matches all the devices in this table.
1298 */
1299 template_disk = dm_table_get_integrity_disk(t);
1300 if (template_disk &&
1301 blk_integrity_compare(dm_disk(t->md), template_disk) >= 0)
1302 return;
1303 }
1293 1304
1294 template_disk = dm_table_get_integrity_disk(t, true); 1305 if (integrity_profile_exists(dm_disk(t->md))) {
1295 if (template_disk)
1296 blk_integrity_register(dm_disk(t->md),
1297 blk_get_integrity(template_disk));
1298 else if (blk_integrity_is_initialized(dm_disk(t->md)))
1299 DMWARN("%s: device no longer has a valid integrity profile",
1300 dm_device_name(t->md));
1301 else
1302 DMWARN("%s: unable to establish an integrity profile", 1306 DMWARN("%s: unable to establish an integrity profile",
1303 dm_device_name(t->md)); 1307 dm_device_name(t->md));
1308 blk_integrity_unregister(dm_disk(t->md));
1309 }
1304} 1310}
1305 1311
1306static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, 1312static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev,
@@ -1500,7 +1506,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1500 else 1506 else
1501 queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q); 1507 queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
1502 1508
1503 dm_table_set_integrity(t); 1509 dm_table_verify_integrity(t);
1504 1510
1505 /* 1511 /*
1506 * Determine whether or not this queue's I/O timings contribute 1512 * Determine whether or not this queue's I/O timings contribute
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c702de18207a..2af9d590e1a0 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1962,12 +1962,9 @@ int md_integrity_register(struct mddev *mddev)
1962 * All component devices are integrity capable and have matching 1962 * All component devices are integrity capable and have matching
1963 * profiles, register the common profile for the md device. 1963 * profiles, register the common profile for the md device.
1964 */ 1964 */
1965 if (blk_integrity_register(mddev->gendisk, 1965 blk_integrity_register(mddev->gendisk,
1966 bdev_get_integrity(reference->bdev)) != 0) { 1966 bdev_get_integrity(reference->bdev));
1967 printk(KERN_ERR "md: failed to register integrity for %s\n", 1967
1968 mdname(mddev));
1969 return -EINVAL;
1970 }
1971 printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev)); 1968 printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev));
1972 if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) { 1969 if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) {
1973 printk(KERN_ERR "md: failed to create integrity pool for %s\n", 1970 printk(KERN_ERR "md: failed to create integrity pool for %s\n",
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index 7df89b547ae1..e85848caf8d2 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -405,7 +405,6 @@ int nd_integrity_init(struct gendisk *disk, unsigned long meta_size)
405 .generate_fn = nd_pi_nop_generate_verify, 405 .generate_fn = nd_pi_nop_generate_verify,
406 .verify_fn = nd_pi_nop_generate_verify, 406 .verify_fn = nd_pi_nop_generate_verify,
407 }; 407 };
408 int ret;
409 408
410 if (meta_size == 0) 409 if (meta_size == 0)
411 return 0; 410 return 0;
@@ -414,10 +413,7 @@ int nd_integrity_init(struct gendisk *disk, unsigned long meta_size)
414 bi.tuple_size = meta_size; 413 bi.tuple_size = meta_size;
415 bi.tag_size = meta_size; 414 bi.tag_size = meta_size;
416 415
417 ret = blk_integrity_register(disk, &bi); 416 blk_integrity_register(disk, &bi);
418 if (ret)
419 return ret;
420
421 blk_queue_max_integrity_segments(disk->queue, 1); 417 blk_queue_max_integrity_segments(disk->queue, 1);
422 418
423 return 0; 419 return 0;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 04e3d60a1e45..8d2aeaaa3895 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -538,7 +538,7 @@ static void nvme_dif_remap(struct request *req,
538 virt = bip_get_seed(bip); 538 virt = bip_get_seed(bip);
539 phys = nvme_block_nr(ns, blk_rq_pos(req)); 539 phys = nvme_block_nr(ns, blk_rq_pos(req));
540 nlb = (blk_rq_bytes(req) >> ns->lba_shift); 540 nlb = (blk_rq_bytes(req) >> ns->lba_shift);
541 ts = ns->disk->integrity->tuple_size; 541 ts = ns->disk->integrity.tuple_size;
542 542
543 for (i = 0; i < nlb; i++, virt++, phys++) { 543 for (i = 0; i < nlb; i++, virt++, phys++) {
544 pi = (struct t10_pi_tuple *)p; 544 pi = (struct t10_pi_tuple *)p;
@@ -2044,8 +2044,7 @@ static int nvme_revalidate_disk(struct gendisk *disk)
2044 ns->pi_type = pi_type; 2044 ns->pi_type = pi_type;
2045 blk_queue_logical_block_size(ns->queue, bs); 2045 blk_queue_logical_block_size(ns->queue, bs);
2046 2046
2047 if (ns->ms && !blk_get_integrity(disk) && (disk->flags & GENHD_FL_UP) && 2047 if (ns->ms && !ns->ext)
2048 !ns->ext)
2049 nvme_init_integrity(ns); 2048 nvme_init_integrity(ns);
2050 2049
2051 if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk)) 2050 if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk))
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 073bb57adab1..0a793c7930eb 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1075,7 +1075,7 @@ int revalidate_disk(struct gendisk *disk)
1075 1075
1076 if (disk->fops->revalidate_disk) 1076 if (disk->fops->revalidate_disk)
1077 ret = disk->fops->revalidate_disk(disk); 1077 ret = disk->fops->revalidate_disk(disk);
1078 1078 blk_integrity_revalidate(disk);
1079 bdev = bdget_disk(disk, 0); 1079 bdev = bdget_disk(disk, 0);
1080 if (!bdev) 1080 if (!bdev)
1081 return ret; 1081 return ret;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 4f1968f15e30..60669c20190f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1468,16 +1468,7 @@ struct blk_integrity_profile {
1468 const char *name; 1468 const char *name;
1469}; 1469};
1470 1470
1471struct blk_integrity { 1471extern void blk_integrity_register(struct gendisk *, struct blk_integrity *);
1472 struct blk_integrity_profile *profile;
1473 unsigned char flags;
1474 unsigned char tuple_size;
1475 unsigned char interval_exp;
1476 unsigned char tag_size;
1477};
1478
1479extern bool blk_integrity_is_initialized(struct gendisk *);
1480extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
1481extern void blk_integrity_unregister(struct gendisk *); 1472extern void blk_integrity_unregister(struct gendisk *);
1482extern int blk_integrity_compare(struct gendisk *, struct gendisk *); 1473extern int blk_integrity_compare(struct gendisk *, struct gendisk *);
1483extern int blk_rq_map_integrity_sg(struct request_queue *, struct bio *, 1474extern int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
@@ -1488,15 +1479,20 @@ extern bool blk_integrity_merge_rq(struct request_queue *, struct request *,
1488extern bool blk_integrity_merge_bio(struct request_queue *, struct request *, 1479extern bool blk_integrity_merge_bio(struct request_queue *, struct request *,
1489 struct bio *); 1480 struct bio *);
1490 1481
1491static inline 1482static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk)
1492struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
1493{ 1483{
1494 return bdev->bd_disk->integrity; 1484 struct blk_integrity *bi = &disk->integrity;
1485
1486 if (!bi->profile)
1487 return NULL;
1488
1489 return bi;
1495} 1490}
1496 1491
1497static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) 1492static inline
1493struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
1498{ 1494{
1499 return disk->integrity; 1495 return blk_get_integrity(bdev->bd_disk);
1500} 1496}
1501 1497
1502static inline bool blk_integrity_rq(struct request *rq) 1498static inline bool blk_integrity_rq(struct request *rq)
@@ -1570,10 +1566,9 @@ static inline int blk_integrity_compare(struct gendisk *a, struct gendisk *b)
1570{ 1566{
1571 return 0; 1567 return 0;
1572} 1568}
1573static inline int blk_integrity_register(struct gendisk *d, 1569static inline void blk_integrity_register(struct gendisk *d,
1574 struct blk_integrity *b) 1570 struct blk_integrity *b)
1575{ 1571{
1576 return 0;
1577} 1572}
1578static inline void blk_integrity_unregister(struct gendisk *d) 1573static inline void blk_integrity_unregister(struct gendisk *d)
1579{ 1574{
@@ -1598,10 +1593,7 @@ static inline bool blk_integrity_merge_bio(struct request_queue *rq,
1598{ 1593{
1599 return true; 1594 return true;
1600} 1595}
1601static inline bool blk_integrity_is_initialized(struct gendisk *g) 1596
1602{
1603 return 0;
1604}
1605static inline bool integrity_req_gap_back_merge(struct request *req, 1597static inline bool integrity_req_gap_back_merge(struct request *req,
1606 struct bio *next) 1598 struct bio *next)
1607{ 1599{
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 9e6e0dfa97ad..82f4911e0ad8 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -163,6 +163,18 @@ struct disk_part_tbl {
163 163
164struct disk_events; 164struct disk_events;
165 165
166#if defined(CONFIG_BLK_DEV_INTEGRITY)
167
168struct blk_integrity {
169 struct blk_integrity_profile *profile;
170 unsigned char flags;
171 unsigned char tuple_size;
172 unsigned char interval_exp;
173 unsigned char tag_size;
174};
175
176#endif /* CONFIG_BLK_DEV_INTEGRITY */
177
166struct gendisk { 178struct gendisk {
167 /* major, first_minor and minors are input parameters only, 179 /* major, first_minor and minors are input parameters only,
168 * don't use directly. Use disk_devt() and disk_max_parts(). 180 * don't use directly. Use disk_devt() and disk_max_parts().
@@ -198,9 +210,9 @@ struct gendisk {
198 atomic_t sync_io; /* RAID */ 210 atomic_t sync_io; /* RAID */
199 struct disk_events *ev; 211 struct disk_events *ev;
200#ifdef CONFIG_BLK_DEV_INTEGRITY 212#ifdef CONFIG_BLK_DEV_INTEGRITY
201 struct blk_integrity *integrity; 213 struct blk_integrity integrity;
202 struct kobject integrity_kobj; 214 struct kobject integrity_kobj;
203#endif 215#endif /* CONFIG_BLK_DEV_INTEGRITY */
204 int node_id; 216 int node_id;
205}; 217};
206 218
@@ -728,6 +740,16 @@ static inline void part_nr_sects_write(struct hd_struct *part, sector_t size)
728#endif 740#endif
729} 741}
730 742
743#if defined(CONFIG_BLK_DEV_INTEGRITY)
744extern void blk_integrity_add(struct gendisk *);
745extern void blk_integrity_del(struct gendisk *);
746extern void blk_integrity_revalidate(struct gendisk *);
747#else /* CONFIG_BLK_DEV_INTEGRITY */
748static inline void blk_integrity_add(struct gendisk *disk) { }
749static inline void blk_integrity_del(struct gendisk *disk) { }
750static inline void blk_integrity_revalidate(struct gendisk *disk) { }
751#endif /* CONFIG_BLK_DEV_INTEGRITY */
752
731#else /* CONFIG_BLOCK */ 753#else /* CONFIG_BLOCK */
732 754
733static inline void printk_all_partitions(void) { } 755static inline void printk_all_partitions(void) { }