diff options
-rw-r--r-- | drivers/md/raid10.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 3c6b193cefd5..5169ed2a9156 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -97,7 +97,7 @@ static int max_queued_requests = 1024; | |||
97 | 97 | ||
98 | static void allow_barrier(struct r10conf *conf); | 98 | static void allow_barrier(struct r10conf *conf); |
99 | static void lower_barrier(struct r10conf *conf); | 99 | static void lower_barrier(struct r10conf *conf); |
100 | static int enough(struct r10conf *conf, int ignore); | 100 | static int _enough(struct r10conf *conf, int previous, int ignore); |
101 | static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, | 101 | static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, |
102 | int *skipped); | 102 | int *skipped); |
103 | static void reshape_request_write(struct mddev *mddev, struct r10bio *r10_bio); | 103 | static void reshape_request_write(struct mddev *mddev, struct r10bio *r10_bio); |
@@ -392,11 +392,9 @@ static void raid10_end_read_request(struct bio *bio, int error) | |||
392 | * than fail the last device. Here we redefine | 392 | * than fail the last device. Here we redefine |
393 | * "uptodate" to mean "Don't want to retry" | 393 | * "uptodate" to mean "Don't want to retry" |
394 | */ | 394 | */ |
395 | unsigned long flags; | 395 | if (!_enough(conf, test_bit(R10BIO_Previous, &r10_bio->state), |
396 | spin_lock_irqsave(&conf->device_lock, flags); | 396 | rdev->raid_disk)) |
397 | if (!enough(conf, rdev->raid_disk)) | ||
398 | uptodate = 1; | 397 | uptodate = 1; |
399 | spin_unlock_irqrestore(&conf->device_lock, flags); | ||
400 | } | 398 | } |
401 | if (uptodate) { | 399 | if (uptodate) { |
402 | raid_end_bio_io(r10_bio); | 400 | raid_end_bio_io(r10_bio); |
@@ -1632,9 +1630,17 @@ static void status(struct seq_file *seq, struct mddev *mddev) | |||
1632 | * Don't consider the device numbered 'ignore' | 1630 | * Don't consider the device numbered 'ignore' |
1633 | * as we might be about to remove it. | 1631 | * as we might be about to remove it. |
1634 | */ | 1632 | */ |
1635 | static int _enough(struct r10conf *conf, struct geom *geo, int ignore) | 1633 | static int _enough(struct r10conf *conf, int previous, int ignore) |
1636 | { | 1634 | { |
1637 | int first = 0; | 1635 | int first = 0; |
1636 | int disks, ncopies; | ||
1637 | if (previous) { | ||
1638 | disks = conf->prev.raid_disks; | ||
1639 | ncopies = conf->prev.near_copies; | ||
1640 | } else { | ||
1641 | disks = conf->geo.raid_disks; | ||
1642 | ncopies = conf->geo.near_copies; | ||
1643 | } | ||
1638 | 1644 | ||
1639 | do { | 1645 | do { |
1640 | int n = conf->copies; | 1646 | int n = conf->copies; |
@@ -1644,25 +1650,31 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore) | |||
1644 | if (conf->mirrors[this].rdev && | 1650 | if (conf->mirrors[this].rdev && |
1645 | this != ignore) | 1651 | this != ignore) |
1646 | cnt++; | 1652 | cnt++; |
1647 | this = (this+1) % geo->raid_disks; | 1653 | this = (this+1) % disks; |
1648 | } | 1654 | } |
1649 | if (cnt == 0) | 1655 | if (cnt == 0) |
1650 | return 0; | 1656 | return 0; |
1651 | first = (first + geo->near_copies) % geo->raid_disks; | 1657 | first = (first + ncopies) % disks; |
1652 | } while (first != 0); | 1658 | } while (first != 0); |
1653 | return 1; | 1659 | return 1; |
1654 | } | 1660 | } |
1655 | 1661 | ||
1656 | static int enough(struct r10conf *conf, int ignore) | 1662 | static int enough(struct r10conf *conf, int ignore) |
1657 | { | 1663 | { |
1658 | return _enough(conf, &conf->geo, ignore) && | 1664 | /* when calling 'enough', both 'prev' and 'geo' must |
1659 | _enough(conf, &conf->prev, ignore); | 1665 | * be stable. |
1666 | * This is ensured if ->reconfig_mutex or ->device_lock | ||
1667 | * is held. | ||
1668 | */ | ||
1669 | return _enough(conf, 0, ignore) && | ||
1670 | _enough(conf, 1, ignore); | ||
1660 | } | 1671 | } |
1661 | 1672 | ||
1662 | static void error(struct mddev *mddev, struct md_rdev *rdev) | 1673 | static void error(struct mddev *mddev, struct md_rdev *rdev) |
1663 | { | 1674 | { |
1664 | char b[BDEVNAME_SIZE]; | 1675 | char b[BDEVNAME_SIZE]; |
1665 | struct r10conf *conf = mddev->private; | 1676 | struct r10conf *conf = mddev->private; |
1677 | unsigned long flags; | ||
1666 | 1678 | ||
1667 | /* | 1679 | /* |
1668 | * If it is not operational, then we have already marked it as dead | 1680 | * If it is not operational, then we have already marked it as dead |
@@ -1670,18 +1682,18 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) | |||
1670 | * next level up know. | 1682 | * next level up know. |
1671 | * else mark the drive as failed | 1683 | * else mark the drive as failed |
1672 | */ | 1684 | */ |
1685 | spin_lock_irqsave(&conf->device_lock, flags); | ||
1673 | if (test_bit(In_sync, &rdev->flags) | 1686 | if (test_bit(In_sync, &rdev->flags) |
1674 | && !enough(conf, rdev->raid_disk)) | 1687 | && !enough(conf, rdev->raid_disk)) { |
1675 | /* | 1688 | /* |
1676 | * Don't fail the drive, just return an IO error. | 1689 | * Don't fail the drive, just return an IO error. |
1677 | */ | 1690 | */ |
1691 | spin_unlock_irqrestore(&conf->device_lock, flags); | ||
1678 | return; | 1692 | return; |
1693 | } | ||
1679 | if (test_and_clear_bit(In_sync, &rdev->flags)) { | 1694 | if (test_and_clear_bit(In_sync, &rdev->flags)) { |
1680 | unsigned long flags; | ||
1681 | spin_lock_irqsave(&conf->device_lock, flags); | ||
1682 | mddev->degraded++; | 1695 | mddev->degraded++; |
1683 | spin_unlock_irqrestore(&conf->device_lock, flags); | 1696 | /* |
1684 | /* | ||
1685 | * if recovery is running, make sure it aborts. | 1697 | * if recovery is running, make sure it aborts. |
1686 | */ | 1698 | */ |
1687 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 1699 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
@@ -1689,6 +1701,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) | |||
1689 | set_bit(Blocked, &rdev->flags); | 1701 | set_bit(Blocked, &rdev->flags); |
1690 | set_bit(Faulty, &rdev->flags); | 1702 | set_bit(Faulty, &rdev->flags); |
1691 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 1703 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
1704 | spin_unlock_irqrestore(&conf->device_lock, flags); | ||
1692 | printk(KERN_ALERT | 1705 | printk(KERN_ALERT |
1693 | "md/raid10:%s: Disk failure on %s, disabling device.\n" | 1706 | "md/raid10:%s: Disk failure on %s, disabling device.\n" |
1694 | "md/raid10:%s: Operation continuing on %d devices.\n", | 1707 | "md/raid10:%s: Operation continuing on %d devices.\n", |
@@ -1791,7 +1804,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
1791 | * very different from resync | 1804 | * very different from resync |
1792 | */ | 1805 | */ |
1793 | return -EBUSY; | 1806 | return -EBUSY; |
1794 | if (rdev->saved_raid_disk < 0 && !_enough(conf, &conf->prev, -1)) | 1807 | if (rdev->saved_raid_disk < 0 && !_enough(conf, 1, -1)) |
1795 | return -EINVAL; | 1808 | return -EINVAL; |
1796 | 1809 | ||
1797 | if (rdev->raid_disk >= 0) | 1810 | if (rdev->raid_disk >= 0) |