diff options
-rw-r--r-- | Documentation/device-mapper/dm-raid.txt | 1 | ||||
-rw-r--r-- | drivers/md/dm-raid.c | 44 | ||||
-rw-r--r-- | drivers/md/raid1.c | 7 | ||||
-rw-r--r-- | drivers/md/raid10.c | 10 |
4 files changed, 54 insertions, 8 deletions
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt index e9192283e5a5..2bb3a6823dc7 100644 --- a/Documentation/device-mapper/dm-raid.txt +++ b/Documentation/device-mapper/dm-raid.txt | |||
@@ -222,3 +222,4 @@ Version History | |||
222 | 1.4.2 Add RAID10 "far" and "offset" algorithm support. | 222 | 1.4.2 Add RAID10 "far" and "offset" algorithm support. |
223 | 1.5.0 Add message interface to allow manipulation of the sync_action. | 223 | 1.5.0 Add message interface to allow manipulation of the sync_action. |
224 | New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt. | 224 | New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt. |
225 | 1.5.1 Add ability to restore transiently failed devices on resume. | ||
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 1d3fe1a40a9b..facaf9142d5a 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -1574,12 +1574,54 @@ static void raid_postsuspend(struct dm_target *ti) | |||
1574 | 1574 | ||
1575 | static void raid_resume(struct dm_target *ti) | 1575 | static void raid_resume(struct dm_target *ti) |
1576 | { | 1576 | { |
1577 | int i; | ||
1578 | uint64_t failed_devices, cleared_failed_devices = 0; | ||
1579 | unsigned long flags; | ||
1580 | struct dm_raid_superblock *sb; | ||
1577 | struct raid_set *rs = ti->private; | 1581 | struct raid_set *rs = ti->private; |
1582 | struct md_rdev *r; | ||
1578 | 1583 | ||
1579 | set_bit(MD_CHANGE_DEVS, &rs->md.flags); | 1584 | set_bit(MD_CHANGE_DEVS, &rs->md.flags); |
1580 | if (!rs->bitmap_loaded) { | 1585 | if (!rs->bitmap_loaded) { |
1581 | bitmap_load(&rs->md); | 1586 | bitmap_load(&rs->md); |
1582 | rs->bitmap_loaded = 1; | 1587 | rs->bitmap_loaded = 1; |
1588 | } else { | ||
1589 | /* | ||
1590 | * A secondary resume while the device is active. | ||
1591 | * Take this opportunity to check whether any failed | ||
1592 | * devices are reachable again. | ||
1593 | */ | ||
1594 | for (i = 0; i < rs->md.raid_disks; i++) { | ||
1595 | r = &rs->dev[i].rdev; | ||
1596 | if (test_bit(Faulty, &r->flags) && r->sb_page && | ||
1597 | sync_page_io(r, 0, r->sb_size, | ||
1598 | r->sb_page, READ, 1)) { | ||
1599 | DMINFO("Faulty device #%d has readable super" | ||
1600 | "block. Attempting to revive it.", i); | ||
1601 | r->raid_disk = i; | ||
1602 | r->saved_raid_disk = i; | ||
1603 | flags = r->flags; | ||
1604 | clear_bit(Faulty, &r->flags); | ||
1605 | clear_bit(WriteErrorSeen, &r->flags); | ||
1606 | clear_bit(In_sync, &r->flags); | ||
1607 | if (r->mddev->pers->hot_add_disk(r->mddev, r)) { | ||
1608 | r->raid_disk = -1; | ||
1609 | r->saved_raid_disk = -1; | ||
1610 | r->flags = flags; | ||
1611 | } else { | ||
1612 | r->recovery_offset = 0; | ||
1613 | cleared_failed_devices |= 1 << i; | ||
1614 | } | ||
1615 | } | ||
1616 | } | ||
1617 | if (cleared_failed_devices) { | ||
1618 | rdev_for_each(r, &rs->md) { | ||
1619 | sb = page_address(r->sb_page); | ||
1620 | failed_devices = le64_to_cpu(sb->failed_devices); | ||
1621 | failed_devices &= ~cleared_failed_devices; | ||
1622 | sb->failed_devices = cpu_to_le64(failed_devices); | ||
1623 | } | ||
1624 | } | ||
1583 | } | 1625 | } |
1584 | 1626 | ||
1585 | clear_bit(MD_RECOVERY_FROZEN, &rs->md.recovery); | 1627 | clear_bit(MD_RECOVERY_FROZEN, &rs->md.recovery); |
@@ -1588,7 +1630,7 @@ static void raid_resume(struct dm_target *ti) | |||
1588 | 1630 | ||
1589 | static struct target_type raid_target = { | 1631 | static struct target_type raid_target = { |
1590 | .name = "raid", | 1632 | .name = "raid", |
1591 | .version = {1, 5, 0}, | 1633 | .version = {1, 5, 1}, |
1592 | .module = THIS_MODULE, | 1634 | .module = THIS_MODULE, |
1593 | .ctr = raid_ctr, | 1635 | .ctr = raid_ctr, |
1594 | .dtr = raid_dtr, | 1636 | .dtr = raid_dtr, |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 6e17f8181c4b..ec734588a1c6 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1519,8 +1519,9 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
1519 | p = conf->mirrors+mirror; | 1519 | p = conf->mirrors+mirror; |
1520 | if (!p->rdev) { | 1520 | if (!p->rdev) { |
1521 | 1521 | ||
1522 | disk_stack_limits(mddev->gendisk, rdev->bdev, | 1522 | if (mddev->gendisk) |
1523 | rdev->data_offset << 9); | 1523 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
1524 | rdev->data_offset << 9); | ||
1524 | 1525 | ||
1525 | p->head_position = 0; | 1526 | p->head_position = 0; |
1526 | rdev->raid_disk = mirror; | 1527 | rdev->raid_disk = mirror; |
@@ -1559,7 +1560,7 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
1559 | clear_bit(Unmerged, &rdev->flags); | 1560 | clear_bit(Unmerged, &rdev->flags); |
1560 | } | 1561 | } |
1561 | md_integrity_add_rdev(rdev, mddev); | 1562 | md_integrity_add_rdev(rdev, mddev); |
1562 | if (blk_queue_discard(bdev_get_queue(rdev->bdev))) | 1563 | if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev))) |
1563 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); | 1564 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); |
1564 | print_conf(conf); | 1565 | print_conf(conf); |
1565 | return err; | 1566 | return err; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 6ddae2501b9a..3c6b193cefd5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1819,15 +1819,17 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
1819 | set_bit(Replacement, &rdev->flags); | 1819 | set_bit(Replacement, &rdev->flags); |
1820 | rdev->raid_disk = mirror; | 1820 | rdev->raid_disk = mirror; |
1821 | err = 0; | 1821 | err = 0; |
1822 | disk_stack_limits(mddev->gendisk, rdev->bdev, | 1822 | if (mddev->gendisk) |
1823 | rdev->data_offset << 9); | 1823 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
1824 | rdev->data_offset << 9); | ||
1824 | conf->fullsync = 1; | 1825 | conf->fullsync = 1; |
1825 | rcu_assign_pointer(p->replacement, rdev); | 1826 | rcu_assign_pointer(p->replacement, rdev); |
1826 | break; | 1827 | break; |
1827 | } | 1828 | } |
1828 | 1829 | ||
1829 | disk_stack_limits(mddev->gendisk, rdev->bdev, | 1830 | if (mddev->gendisk) |
1830 | rdev->data_offset << 9); | 1831 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
1832 | rdev->data_offset << 9); | ||
1831 | 1833 | ||
1832 | p->head_position = 0; | 1834 | p->head_position = 0; |
1833 | p->recovery_disabled = mddev->recovery_disabled - 1; | 1835 | p->recovery_disabled = mddev->recovery_disabled - 1; |