diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-03-02 17:03:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-03-02 17:03:27 -0500 |
commit | 1a6f77ab08d41ef0ec543fa29bf5040c10b5651a (patch) | |
tree | ab364ff196fa661a450dc054d354a75bba157ac0 | |
parent | 49db1f0ef2df10de1dfd40c8d66e4379d953640f (diff) | |
parent | 750f199ee8b578062341e6ddfe36c59ac8ff2dcb (diff) |
Merge tag 'md/4.0-fixes' of git://neil.brown.name/md
Pull md fixes from Neil Brown:
"Three md fixes:
- fix a read-balance problem that was reported 2 years ago, but that
I never noticed the report :-(
- fix for rare RAID6 problem causing incorrect bitmap updates when
two devices fail.
- add __ATTR_PREALLOC annotation now that it is possible"
* tag 'md/4.0-fixes' of git://neil.brown.name/md:
md: mark some attributes as pre-alloc
raid5: check faulty flag for array status during recovery.
md/raid1: fix read balance when a drive is write-mostly.
-rw-r--r-- | drivers/md/md.c | 14 | ||||
-rw-r--r-- | drivers/md/raid1.c | 5 | ||||
-rw-r--r-- | drivers/md/raid5.c | 13 |
3 files changed, 20 insertions, 12 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index c8d2bac4e28b..cadf9cc02b25 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -2555,7 +2555,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2555 | return err ? err : len; | 2555 | return err ? err : len; |
2556 | } | 2556 | } |
2557 | static struct rdev_sysfs_entry rdev_state = | 2557 | static struct rdev_sysfs_entry rdev_state = |
2558 | __ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store); | 2558 | __ATTR_PREALLOC(state, S_IRUGO|S_IWUSR, state_show, state_store); |
2559 | 2559 | ||
2560 | static ssize_t | 2560 | static ssize_t |
2561 | errors_show(struct md_rdev *rdev, char *page) | 2561 | errors_show(struct md_rdev *rdev, char *page) |
@@ -3638,7 +3638,8 @@ resync_start_store(struct mddev *mddev, const char *buf, size_t len) | |||
3638 | return err ?: len; | 3638 | return err ?: len; |
3639 | } | 3639 | } |
3640 | static struct md_sysfs_entry md_resync_start = | 3640 | static struct md_sysfs_entry md_resync_start = |
3641 | __ATTR(resync_start, S_IRUGO|S_IWUSR, resync_start_show, resync_start_store); | 3641 | __ATTR_PREALLOC(resync_start, S_IRUGO|S_IWUSR, |
3642 | resync_start_show, resync_start_store); | ||
3642 | 3643 | ||
3643 | /* | 3644 | /* |
3644 | * The array state can be: | 3645 | * The array state can be: |
@@ -3851,7 +3852,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3851 | return err ?: len; | 3852 | return err ?: len; |
3852 | } | 3853 | } |
3853 | static struct md_sysfs_entry md_array_state = | 3854 | static struct md_sysfs_entry md_array_state = |
3854 | __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store); | 3855 | __ATTR_PREALLOC(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store); |
3855 | 3856 | ||
3856 | static ssize_t | 3857 | static ssize_t |
3857 | max_corrected_read_errors_show(struct mddev *mddev, char *page) { | 3858 | max_corrected_read_errors_show(struct mddev *mddev, char *page) { |
@@ -4101,7 +4102,7 @@ out_unlock: | |||
4101 | } | 4102 | } |
4102 | 4103 | ||
4103 | static struct md_sysfs_entry md_metadata = | 4104 | static struct md_sysfs_entry md_metadata = |
4104 | __ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store); | 4105 | __ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store); |
4105 | 4106 | ||
4106 | static ssize_t | 4107 | static ssize_t |
4107 | action_show(struct mddev *mddev, char *page) | 4108 | action_show(struct mddev *mddev, char *page) |
@@ -4189,7 +4190,7 @@ action_store(struct mddev *mddev, const char *page, size_t len) | |||
4189 | } | 4190 | } |
4190 | 4191 | ||
4191 | static struct md_sysfs_entry md_scan_mode = | 4192 | static struct md_sysfs_entry md_scan_mode = |
4192 | __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store); | 4193 | __ATTR_PREALLOC(sync_action, S_IRUGO|S_IWUSR, action_show, action_store); |
4193 | 4194 | ||
4194 | static ssize_t | 4195 | static ssize_t |
4195 | last_sync_action_show(struct mddev *mddev, char *page) | 4196 | last_sync_action_show(struct mddev *mddev, char *page) |
@@ -4335,7 +4336,8 @@ sync_completed_show(struct mddev *mddev, char *page) | |||
4335 | return sprintf(page, "%llu / %llu\n", resync, max_sectors); | 4336 | return sprintf(page, "%llu / %llu\n", resync, max_sectors); |
4336 | } | 4337 | } |
4337 | 4338 | ||
4338 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); | 4339 | static struct md_sysfs_entry md_sync_completed = |
4340 | __ATTR_PREALLOC(sync_completed, S_IRUGO, sync_completed_show, NULL); | ||
4339 | 4341 | ||
4340 | static ssize_t | 4342 | static ssize_t |
4341 | min_sync_show(struct mddev *mddev, char *page) | 4343 | min_sync_show(struct mddev *mddev, char *page) |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4153da5d4011..d34e238afa54 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -560,7 +560,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect | |||
560 | if (test_bit(WriteMostly, &rdev->flags)) { | 560 | if (test_bit(WriteMostly, &rdev->flags)) { |
561 | /* Don't balance among write-mostly, just | 561 | /* Don't balance among write-mostly, just |
562 | * use the first as a last resort */ | 562 | * use the first as a last resort */ |
563 | if (best_disk < 0) { | 563 | if (best_dist_disk < 0) { |
564 | if (is_badblock(rdev, this_sector, sectors, | 564 | if (is_badblock(rdev, this_sector, sectors, |
565 | &first_bad, &bad_sectors)) { | 565 | &first_bad, &bad_sectors)) { |
566 | if (first_bad < this_sector) | 566 | if (first_bad < this_sector) |
@@ -569,7 +569,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect | |||
569 | best_good_sectors = first_bad - this_sector; | 569 | best_good_sectors = first_bad - this_sector; |
570 | } else | 570 | } else |
571 | best_good_sectors = sectors; | 571 | best_good_sectors = sectors; |
572 | best_disk = disk; | 572 | best_dist_disk = disk; |
573 | best_pending_disk = disk; | ||
573 | } | 574 | } |
574 | continue; | 575 | continue; |
575 | } | 576 | } |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e75d48c0421a..cd2f96b2c572 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -5121,12 +5121,17 @@ static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int | |||
5121 | schedule_timeout_uninterruptible(1); | 5121 | schedule_timeout_uninterruptible(1); |
5122 | } | 5122 | } |
5123 | /* Need to check if array will still be degraded after recovery/resync | 5123 | /* Need to check if array will still be degraded after recovery/resync |
5124 | * We don't need to check the 'failed' flag as when that gets set, | 5124 | * Note in case of > 1 drive failures it's possible we're rebuilding |
5125 | * recovery aborts. | 5125 | * one drive while leaving another faulty drive in array. |
5126 | */ | 5126 | */ |
5127 | for (i = 0; i < conf->raid_disks; i++) | 5127 | rcu_read_lock(); |
5128 | if (conf->disks[i].rdev == NULL) | 5128 | for (i = 0; i < conf->raid_disks; i++) { |
5129 | struct md_rdev *rdev = ACCESS_ONCE(conf->disks[i].rdev); | ||
5130 | |||
5131 | if (rdev == NULL || test_bit(Faulty, &rdev->flags)) | ||
5129 | still_degraded = 1; | 5132 | still_degraded = 1; |
5133 | } | ||
5134 | rcu_read_unlock(); | ||
5130 | 5135 | ||
5131 | bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded); | 5136 | bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded); |
5132 | 5137 | ||