Commit 1a6f77ab authored by Linus Torvalds's avatar Linus Torvalds

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.
parents 49db1f0e 750f199e
...@@ -2555,7 +2555,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) ...@@ -2555,7 +2555,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
return err ? err : len; return err ? err : len;
} }
static struct rdev_sysfs_entry rdev_state = static struct rdev_sysfs_entry rdev_state =
__ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store); __ATTR_PREALLOC(state, S_IRUGO|S_IWUSR, state_show, state_store);
static ssize_t static ssize_t
errors_show(struct md_rdev *rdev, char *page) 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,7 +3638,8 @@ resync_start_store(struct mddev *mddev, const char *buf, size_t len)
return err ?: len; return err ?: len;
} }
static struct md_sysfs_entry md_resync_start = static struct md_sysfs_entry md_resync_start =
__ATTR(resync_start, S_IRUGO|S_IWUSR, resync_start_show, resync_start_store); __ATTR_PREALLOC(resync_start, S_IRUGO|S_IWUSR,
resync_start_show, resync_start_store);
/* /*
* The array state can be: * The array state can be:
...@@ -3851,7 +3852,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) ...@@ -3851,7 +3852,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
return err ?: len; return err ?: len;
} }
static struct md_sysfs_entry md_array_state = static struct md_sysfs_entry md_array_state =
__ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store); __ATTR_PREALLOC(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
static ssize_t static ssize_t
max_corrected_read_errors_show(struct mddev *mddev, char *page) { max_corrected_read_errors_show(struct mddev *mddev, char *page) {
...@@ -4101,7 +4102,7 @@ metadata_store(struct mddev *mddev, const char *buf, size_t len) ...@@ -4101,7 +4102,7 @@ metadata_store(struct mddev *mddev, const char *buf, size_t len)
} }
static struct md_sysfs_entry md_metadata = static struct md_sysfs_entry md_metadata =
__ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store); __ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
static ssize_t static ssize_t
action_show(struct mddev *mddev, char *page) action_show(struct mddev *mddev, char *page)
...@@ -4189,7 +4190,7 @@ action_store(struct mddev *mddev, const char *page, size_t len) ...@@ -4189,7 +4190,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
} }
static struct md_sysfs_entry md_scan_mode = static struct md_sysfs_entry md_scan_mode =
__ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store); __ATTR_PREALLOC(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
static ssize_t static ssize_t
last_sync_action_show(struct mddev *mddev, char *page) last_sync_action_show(struct mddev *mddev, char *page)
...@@ -4335,7 +4336,8 @@ sync_completed_show(struct mddev *mddev, char *page) ...@@ -4335,7 +4336,8 @@ sync_completed_show(struct mddev *mddev, char *page)
return sprintf(page, "%llu / %llu\n", resync, max_sectors); return sprintf(page, "%llu / %llu\n", resync, max_sectors);
} }
static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); static struct md_sysfs_entry md_sync_completed =
__ATTR_PREALLOC(sync_completed, S_IRUGO, sync_completed_show, NULL);
static ssize_t static ssize_t
min_sync_show(struct mddev *mddev, char *page) min_sync_show(struct mddev *mddev, char *page)
......
...@@ -560,7 +560,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect ...@@ -560,7 +560,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
if (test_bit(WriteMostly, &rdev->flags)) { if (test_bit(WriteMostly, &rdev->flags)) {
/* Don't balance among write-mostly, just /* Don't balance among write-mostly, just
* use the first as a last resort */ * use the first as a last resort */
if (best_disk < 0) { if (best_dist_disk < 0) {
if (is_badblock(rdev, this_sector, sectors, if (is_badblock(rdev, this_sector, sectors,
&first_bad, &bad_sectors)) { &first_bad, &bad_sectors)) {
if (first_bad < this_sector) if (first_bad < this_sector)
...@@ -569,7 +569,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect ...@@ -569,7 +569,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
best_good_sectors = first_bad - this_sector; best_good_sectors = first_bad - this_sector;
} else } else
best_good_sectors = sectors; best_good_sectors = sectors;
best_disk = disk; best_dist_disk = disk;
best_pending_disk = disk;
} }
continue; continue;
} }
......
...@@ -5121,12 +5121,17 @@ static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int ...@@ -5121,12 +5121,17 @@ static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int
schedule_timeout_uninterruptible(1); schedule_timeout_uninterruptible(1);
} }
/* Need to check if array will still be degraded after recovery/resync /* Need to check if array will still be degraded after recovery/resync
* We don't need to check the 'failed' flag as when that gets set, * Note in case of > 1 drive failures it's possible we're rebuilding
* recovery aborts. * one drive while leaving another faulty drive in array.
*/ */
for (i = 0; i < conf->raid_disks; i++) rcu_read_lock();
if (conf->disks[i].rdev == NULL) for (i = 0; i < conf->raid_disks; i++) {
struct md_rdev *rdev = ACCESS_ONCE(conf->disks[i].rdev);
if (rdev == NULL || test_bit(Faulty, &rdev->flags))
still_degraded = 1; still_degraded = 1;
}
rcu_read_unlock();
bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded); bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment