diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 94 |
1 files changed, 64 insertions, 30 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index d4351ff0849f..180949e94a7b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1487,37 +1487,76 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) | |||
1487 | 1487 | ||
1488 | static LIST_HEAD(pending_raid_disks); | 1488 | static LIST_HEAD(pending_raid_disks); |
1489 | 1489 | ||
1490 | static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev) | 1490 | /* |
1491 | * Try to register data integrity profile for an mddev | ||
1492 | * | ||
1493 | * This is called when an array is started and after a disk has been kicked | ||
1494 | * from the array. It only succeeds if all working and active component devices | ||
1495 | * are integrity capable with matching profiles. | ||
1496 | */ | ||
1497 | int md_integrity_register(mddev_t *mddev) | ||
1498 | { | ||
1499 | mdk_rdev_t *rdev, *reference = NULL; | ||
1500 | |||
1501 | if (list_empty(&mddev->disks)) | ||
1502 | return 0; /* nothing to do */ | ||
1503 | if (blk_get_integrity(mddev->gendisk)) | ||
1504 | return 0; /* already registered */ | ||
1505 | list_for_each_entry(rdev, &mddev->disks, same_set) { | ||
1506 | /* skip spares and non-functional disks */ | ||
1507 | if (test_bit(Faulty, &rdev->flags)) | ||
1508 | continue; | ||
1509 | if (rdev->raid_disk < 0) | ||
1510 | continue; | ||
1511 | /* | ||
1512 | * If at least one rdev is not integrity capable, we can not | ||
1513 | * enable data integrity for the md device. | ||
1514 | */ | ||
1515 | if (!bdev_get_integrity(rdev->bdev)) | ||
1516 | return -EINVAL; | ||
1517 | if (!reference) { | ||
1518 | /* Use the first rdev as the reference */ | ||
1519 | reference = rdev; | ||
1520 | continue; | ||
1521 | } | ||
1522 | /* does this rdev's profile match the reference profile? */ | ||
1523 | if (blk_integrity_compare(reference->bdev->bd_disk, | ||
1524 | rdev->bdev->bd_disk) < 0) | ||
1525 | return -EINVAL; | ||
1526 | } | ||
1527 | /* | ||
1528 | * All component devices are integrity capable and have matching | ||
1529 | * profiles, register the common profile for the md device. | ||
1530 | */ | ||
1531 | if (blk_integrity_register(mddev->gendisk, | ||
1532 | bdev_get_integrity(reference->bdev)) != 0) { | ||
1533 | printk(KERN_ERR "md: failed to register integrity for %s\n", | ||
1534 | mdname(mddev)); | ||
1535 | return -EINVAL; | ||
1536 | } | ||
1537 | printk(KERN_NOTICE "md: data integrity on %s enabled\n", | ||
1538 | mdname(mddev)); | ||
1539 | return 0; | ||
1540 | } | ||
1541 | EXPORT_SYMBOL(md_integrity_register); | ||
1542 | |||
1543 | /* Disable data integrity if non-capable/non-matching disk is being added */ | ||
1544 | void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev) | ||
1491 | { | 1545 | { |
1492 | struct mdk_personality *pers = mddev->pers; | ||
1493 | struct gendisk *disk = mddev->gendisk; | ||
1494 | struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev); | 1546 | struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev); |
1495 | struct blk_integrity *bi_mddev = blk_get_integrity(disk); | 1547 | struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk); |
1496 | 1548 | ||
1497 | /* Data integrity passthrough not supported on RAID 4, 5 and 6 */ | 1549 | if (!bi_mddev) /* nothing to do */ |
1498 | if (pers && pers->level >= 4 && pers->level <= 6) | ||
1499 | return; | 1550 | return; |
1500 | 1551 | if (rdev->raid_disk < 0) /* skip spares */ | |
1501 | /* If rdev is integrity capable, register profile for mddev */ | ||
1502 | if (!bi_mddev && bi_rdev) { | ||
1503 | if (blk_integrity_register(disk, bi_rdev)) | ||
1504 | printk(KERN_ERR "%s: %s Could not register integrity!\n", | ||
1505 | __func__, disk->disk_name); | ||
1506 | else | ||
1507 | printk(KERN_NOTICE "Enabling data integrity on %s\n", | ||
1508 | disk->disk_name); | ||
1509 | return; | 1552 | return; |
1510 | } | 1553 | if (bi_rdev && blk_integrity_compare(mddev->gendisk, |
1511 | 1554 | rdev->bdev->bd_disk) >= 0) | |
1512 | /* Check that mddev and rdev have matching profiles */ | 1555 | return; |
1513 | if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) { | 1556 | printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev)); |
1514 | printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__, | 1557 | blk_integrity_unregister(mddev->gendisk); |
1515 | disk->disk_name, rdev->bdev->bd_disk->disk_name); | ||
1516 | printk(KERN_NOTICE "Disabling data integrity on %s\n", | ||
1517 | disk->disk_name); | ||
1518 | blk_integrity_unregister(disk); | ||
1519 | } | ||
1520 | } | 1558 | } |
1559 | EXPORT_SYMBOL(md_integrity_add_rdev); | ||
1521 | 1560 | ||
1522 | static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | 1561 | static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) |
1523 | { | 1562 | { |
@@ -1591,7 +1630,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1591 | /* May as well allow recovery to be retried once */ | 1630 | /* May as well allow recovery to be retried once */ |
1592 | mddev->recovery_disabled = 0; | 1631 | mddev->recovery_disabled = 0; |
1593 | 1632 | ||
1594 | md_integrity_check(rdev, mddev); | ||
1595 | return 0; | 1633 | return 0; |
1596 | 1634 | ||
1597 | fail: | 1635 | fail: |
@@ -4048,10 +4086,6 @@ static int do_md_run(mddev_t * mddev) | |||
4048 | } | 4086 | } |
4049 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | 4087 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); |
4050 | 4088 | ||
4051 | if (pers->level >= 4 && pers->level <= 6) | ||
4052 | /* Cannot support integrity (yet) */ | ||
4053 | blk_integrity_unregister(mddev->gendisk); | ||
4054 | |||
4055 | if (mddev->reshape_position != MaxSector && | 4089 | if (mddev->reshape_position != MaxSector && |
4056 | pers->start_reshape == NULL) { | 4090 | pers->start_reshape == NULL) { |
4057 | /* This personality cannot handle reshaping... */ | 4091 | /* This personality cannot handle reshaping... */ |