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 | ||