|
@@ -2010,28 +2010,32 @@ int md_integrity_register(struct mddev *mddev)
|
|
|
}
|
|
|
EXPORT_SYMBOL(md_integrity_register);
|
|
|
|
|
|
-/* Disable data integrity if non-capable/non-matching disk is being added */
|
|
|
-void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
|
|
+/*
|
|
|
+ * Attempt to add an rdev, but only if it is consistent with the current
|
|
|
+ * integrity profile
|
|
|
+ */
|
|
|
+int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
|
|
{
|
|
|
struct blk_integrity *bi_rdev;
|
|
|
struct blk_integrity *bi_mddev;
|
|
|
+ char name[BDEVNAME_SIZE];
|
|
|
|
|
|
if (!mddev->gendisk)
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
bi_rdev = bdev_get_integrity(rdev->bdev);
|
|
|
bi_mddev = blk_get_integrity(mddev->gendisk);
|
|
|
|
|
|
if (!bi_mddev) /* nothing to do */
|
|
|
- return;
|
|
|
- if (rdev->raid_disk < 0) /* skip spares */
|
|
|
- return;
|
|
|
- if (bi_rdev && blk_integrity_compare(mddev->gendisk,
|
|
|
- rdev->bdev->bd_disk) >= 0)
|
|
|
- return;
|
|
|
- WARN_ON_ONCE(!mddev->suspended);
|
|
|
- printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
|
|
|
- blk_integrity_unregister(mddev->gendisk);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
|
|
|
+ printk(KERN_NOTICE "%s: incompatible integrity profile for %s\n",
|
|
|
+ mdname(mddev), bdevname(rdev->bdev, name));
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL(md_integrity_add_rdev);
|
|
|
|