diff options
Diffstat (limited to 'drivers/md/md.c')
| -rw-r--r-- | drivers/md/md.c | 144 |
1 files changed, 89 insertions, 55 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index d4351ff0849f..5b98bea4ff9b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -1308,7 +1308,12 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1308 | } | 1308 | } |
| 1309 | if (mddev->level != LEVEL_MULTIPATH) { | 1309 | if (mddev->level != LEVEL_MULTIPATH) { |
| 1310 | int role; | 1310 | int role; |
| 1311 | role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); | 1311 | if (rdev->desc_nr < 0 || |
| 1312 | rdev->desc_nr >= le32_to_cpu(sb->max_dev)) { | ||
| 1313 | role = 0xffff; | ||
| 1314 | rdev->desc_nr = -1; | ||
| 1315 | } else | ||
| 1316 | role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); | ||
| 1312 | switch(role) { | 1317 | switch(role) { |
| 1313 | case 0xffff: /* spare */ | 1318 | case 0xffff: /* spare */ |
| 1314 | break; | 1319 | break; |
| @@ -1394,8 +1399,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1394 | if (rdev2->desc_nr+1 > max_dev) | 1399 | if (rdev2->desc_nr+1 > max_dev) |
| 1395 | max_dev = rdev2->desc_nr+1; | 1400 | max_dev = rdev2->desc_nr+1; |
| 1396 | 1401 | ||
| 1397 | if (max_dev > le32_to_cpu(sb->max_dev)) | 1402 | if (max_dev > le32_to_cpu(sb->max_dev)) { |
| 1403 | int bmask; | ||
| 1398 | sb->max_dev = cpu_to_le32(max_dev); | 1404 | sb->max_dev = cpu_to_le32(max_dev); |
| 1405 | rdev->sb_size = max_dev * 2 + 256; | ||
| 1406 | bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; | ||
| 1407 | if (rdev->sb_size & bmask) | ||
| 1408 | rdev->sb_size = (rdev->sb_size | bmask) + 1; | ||
| 1409 | } | ||
| 1399 | for (i=0; i<max_dev;i++) | 1410 | for (i=0; i<max_dev;i++) |
| 1400 | sb->dev_roles[i] = cpu_to_le16(0xfffe); | 1411 | sb->dev_roles[i] = cpu_to_le16(0xfffe); |
| 1401 | 1412 | ||
| @@ -1487,37 +1498,76 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) | |||
| 1487 | 1498 | ||
| 1488 | static LIST_HEAD(pending_raid_disks); | 1499 | static LIST_HEAD(pending_raid_disks); |
| 1489 | 1500 | ||
| 1490 | static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev) | 1501 | /* |
| 1502 | * Try to register data integrity profile for an mddev | ||
| 1503 | * | ||
| 1504 | * This is called when an array is started and after a disk has been kicked | ||
| 1505 | * from the array. It only succeeds if all working and active component devices | ||
| 1506 | * are integrity capable with matching profiles. | ||
| 1507 | */ | ||
| 1508 | int md_integrity_register(mddev_t *mddev) | ||
| 1509 | { | ||
| 1510 | mdk_rdev_t *rdev, *reference = NULL; | ||
| 1511 | |||
| 1512 | if (list_empty(&mddev->disks)) | ||
| 1513 | return 0; /* nothing to do */ | ||
| 1514 | if (blk_get_integrity(mddev->gendisk)) | ||
| 1515 | return 0; /* already registered */ | ||
| 1516 | list_for_each_entry(rdev, &mddev->disks, same_set) { | ||
| 1517 | /* skip spares and non-functional disks */ | ||
| 1518 | if (test_bit(Faulty, &rdev->flags)) | ||
| 1519 | continue; | ||
| 1520 | if (rdev->raid_disk < 0) | ||
| 1521 | continue; | ||
| 1522 | /* | ||
| 1523 | * If at least one rdev is not integrity capable, we can not | ||
| 1524 | * enable data integrity for the md device. | ||
| 1525 | */ | ||
| 1526 | if (!bdev_get_integrity(rdev->bdev)) | ||
| 1527 | return -EINVAL; | ||
| 1528 | if (!reference) { | ||
| 1529 | /* Use the first rdev as the reference */ | ||
| 1530 | reference = rdev; | ||
| 1531 | continue; | ||
| 1532 | } | ||
| 1533 | /* does this rdev's profile match the reference profile? */ | ||
| 1534 | if (blk_integrity_compare(reference->bdev->bd_disk, | ||
| 1535 | rdev->bdev->bd_disk) < 0) | ||
| 1536 | return -EINVAL; | ||
| 1537 | } | ||
| 1538 | /* | ||
| 1539 | * All component devices are integrity capable and have matching | ||
| 1540 | * profiles, register the common profile for the md device. | ||
| 1541 | */ | ||
| 1542 | if (blk_integrity_register(mddev->gendisk, | ||
| 1543 | bdev_get_integrity(reference->bdev)) != 0) { | ||
| 1544 | printk(KERN_ERR "md: failed to register integrity for %s\n", | ||
| 1545 | mdname(mddev)); | ||
| 1546 | return -EINVAL; | ||
| 1547 | } | ||
| 1548 | printk(KERN_NOTICE "md: data integrity on %s enabled\n", | ||
| 1549 | mdname(mddev)); | ||
| 1550 | return 0; | ||
| 1551 | } | ||
| 1552 | EXPORT_SYMBOL(md_integrity_register); | ||
| 1553 | |||
| 1554 | /* Disable data integrity if non-capable/non-matching disk is being added */ | ||
| 1555 | void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev) | ||
| 1491 | { | 1556 | { |
| 1492 | struct mdk_personality *pers = mddev->pers; | ||
| 1493 | struct gendisk *disk = mddev->gendisk; | ||
| 1494 | struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev); | 1557 | struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev); |
| 1495 | struct blk_integrity *bi_mddev = blk_get_integrity(disk); | 1558 | struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk); |
| 1496 | 1559 | ||
| 1497 | /* Data integrity passthrough not supported on RAID 4, 5 and 6 */ | 1560 | if (!bi_mddev) /* nothing to do */ |
| 1498 | if (pers && pers->level >= 4 && pers->level <= 6) | ||
| 1499 | return; | 1561 | return; |
| 1500 | 1562 | 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; | 1563 | return; |
| 1510 | } | 1564 | if (bi_rdev && blk_integrity_compare(mddev->gendisk, |
| 1511 | 1565 | rdev->bdev->bd_disk) >= 0) | |
| 1512 | /* Check that mddev and rdev have matching profiles */ | 1566 | return; |
| 1513 | if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) { | 1567 | printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev)); |
| 1514 | printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__, | 1568 | 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 | } | 1569 | } |
| 1570 | EXPORT_SYMBOL(md_integrity_add_rdev); | ||
| 1521 | 1571 | ||
| 1522 | static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | 1572 | static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) |
| 1523 | { | 1573 | { |
| @@ -1591,7 +1641,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
| 1591 | /* May as well allow recovery to be retried once */ | 1641 | /* May as well allow recovery to be retried once */ |
| 1592 | mddev->recovery_disabled = 0; | 1642 | mddev->recovery_disabled = 0; |
| 1593 | 1643 | ||
| 1594 | md_integrity_check(rdev, mddev); | ||
| 1595 | return 0; | 1644 | return 0; |
| 1596 | 1645 | ||
| 1597 | fail: | 1646 | fail: |
| @@ -2657,6 +2706,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 2657 | ssize_t rv = len; | 2706 | ssize_t rv = len; |
| 2658 | struct mdk_personality *pers; | 2707 | struct mdk_personality *pers; |
| 2659 | void *priv; | 2708 | void *priv; |
| 2709 | mdk_rdev_t *rdev; | ||
| 2660 | 2710 | ||
| 2661 | if (mddev->pers == NULL) { | 2711 | if (mddev->pers == NULL) { |
| 2662 | if (len == 0) | 2712 | if (len == 0) |
| @@ -2736,6 +2786,12 @@ level_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 2736 | mddev_suspend(mddev); | 2786 | mddev_suspend(mddev); |
| 2737 | mddev->pers->stop(mddev); | 2787 | mddev->pers->stop(mddev); |
| 2738 | module_put(mddev->pers->owner); | 2788 | module_put(mddev->pers->owner); |
| 2789 | /* Invalidate devices that are now superfluous */ | ||
| 2790 | list_for_each_entry(rdev, &mddev->disks, same_set) | ||
| 2791 | if (rdev->raid_disk >= mddev->raid_disks) { | ||
| 2792 | rdev->raid_disk = -1; | ||
| 2793 | clear_bit(In_sync, &rdev->flags); | ||
| 2794 | } | ||
| 2739 | mddev->pers = pers; | 2795 | mddev->pers = pers; |
| 2740 | mddev->private = priv; | 2796 | mddev->private = priv; |
| 2741 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | 2797 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); |
| @@ -3685,17 +3741,8 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 3685 | 3741 | ||
| 3686 | mddev->array_sectors = sectors; | 3742 | mddev->array_sectors = sectors; |
| 3687 | set_capacity(mddev->gendisk, mddev->array_sectors); | 3743 | set_capacity(mddev->gendisk, mddev->array_sectors); |
| 3688 | if (mddev->pers) { | 3744 | if (mddev->pers) |
| 3689 | struct block_device *bdev = bdget_disk(mddev->gendisk, 0); | 3745 | revalidate_disk(mddev->gendisk); |
| 3690 | |||
| 3691 | if (bdev) { | ||
| 3692 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
| 3693 | i_size_write(bdev->bd_inode, | ||
| 3694 | (loff_t)mddev->array_sectors << 9); | ||
| 3695 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
| 3696 | bdput(bdev); | ||
| 3697 | } | ||
| 3698 | } | ||
| 3699 | 3746 | ||
| 3700 | return len; | 3747 | return len; |
| 3701 | } | 3748 | } |
| @@ -4048,10 +4095,6 @@ static int do_md_run(mddev_t * mddev) | |||
| 4048 | } | 4095 | } |
| 4049 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | 4096 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); |
| 4050 | 4097 | ||
| 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 && | 4098 | if (mddev->reshape_position != MaxSector && |
| 4056 | pers->start_reshape == NULL) { | 4099 | pers->start_reshape == NULL) { |
| 4057 | /* This personality cannot handle reshaping... */ | 4100 | /* This personality cannot handle reshaping... */ |
| @@ -4189,6 +4232,7 @@ static int do_md_run(mddev_t * mddev) | |||
| 4189 | md_wakeup_thread(mddev->thread); | 4232 | md_wakeup_thread(mddev->thread); |
| 4190 | md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ | 4233 | md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ |
| 4191 | 4234 | ||
| 4235 | revalidate_disk(mddev->gendisk); | ||
| 4192 | mddev->changed = 1; | 4236 | mddev->changed = 1; |
| 4193 | md_new_event(mddev); | 4237 | md_new_event(mddev); |
| 4194 | sysfs_notify_dirent(mddev->sysfs_state); | 4238 | sysfs_notify_dirent(mddev->sysfs_state); |
| @@ -5087,18 +5131,8 @@ static int update_size(mddev_t *mddev, sector_t num_sectors) | |||
| 5087 | return -ENOSPC; | 5131 | return -ENOSPC; |
| 5088 | } | 5132 | } |
| 5089 | rv = mddev->pers->resize(mddev, num_sectors); | 5133 | rv = mddev->pers->resize(mddev, num_sectors); |
| 5090 | if (!rv) { | 5134 | if (!rv) |
| 5091 | struct block_device *bdev; | 5135 | revalidate_disk(mddev->gendisk); |
| 5092 | |||
| 5093 | bdev = bdget_disk(mddev->gendisk, 0); | ||
| 5094 | if (bdev) { | ||
| 5095 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
| 5096 | i_size_write(bdev->bd_inode, | ||
| 5097 | (loff_t)mddev->array_sectors << 9); | ||
| 5098 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
| 5099 | bdput(bdev); | ||
| 5100 | } | ||
| 5101 | } | ||
| 5102 | return rv; | 5136 | return rv; |
| 5103 | } | 5137 | } |
| 5104 | 5138 | ||
