summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/blk-integrity.c160
-rw-r--r--block/genhd.c2
-rw-r--r--block/partition-generic.c1
3 files changed, 61 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);
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)))