summaryrefslogtreecommitdiffstats
path: root/block/blk-integrity.c
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 /block/blk-integrity.c
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>
Diffstat (limited to 'block/blk-integrity.c')
-rw-r--r--block/blk-integrity.c160
1 files changed, 58 insertions, 102 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);