aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-raid.c
diff options
context:
space:
mode:
authorJonathan Brassow <jbrassow@redhat.com>2017-10-02 18:17:35 -0400
committerMike Snitzer <snitzer@redhat.com>2017-10-05 16:21:30 -0400
commit41dcf197ad5373a7dd0a4b6572aec2e3ec6a0e49 (patch)
treee2ac2abc5fa116104174a29d2f0878bf59b6ab2e /drivers/md/dm-raid.c
parent783874b050768d361239e444ba0fa396bb6d463f (diff)
dm raid: fix incorrect status output at the end of a "recover" process
There are three important fields that indicate the overall health and status of an array: dev_health, sync_ratio, and sync_action. They tell us the condition of the devices in the array, and the degree to which the array is synchronized. This commit fixes a condition that is reported incorrectly. When a member of the array is being rebuilt or a new device is added, the "recover" process is used to synchronize it with the rest of the array. When the process is complete, but the sync thread hasn't yet been reaped, it is possible for the state of MD to be: mddev->recovery = [ MD_RECOVERY_RUNNING MD_RECOVERY_RECOVER MD_RECOVERY_DONE ] curr_resync_completed = <max dev size> (but not MaxSector) and all rdevs to be In_sync. This causes the 'array_in_sync' output parameter that is passed to rs_get_progress() to be computed incorrectly and reported as 'false' -- or not in-sync. This in turn causes the dev_health status characters to be reported as all 'a', rather than the proper 'A'. This can cause erroneous output for several seconds at a time when tools will want to be checking the condition due to events that are raised at the end of a sync process. Fix this by properly calculating the 'array_in_sync' return parameter in rs_get_progress(). Also, remove an unnecessary intermediate 'recovery_cp' variable in rs_get_progress(). Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r--drivers/md/dm-raid.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 5bfe285ea9d1..43094ea89e37 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3297,11 +3297,10 @@ static const char *__raid_dev_status(struct raid_set *rs, struct md_rdev *rdev,
3297static sector_t rs_get_progress(struct raid_set *rs, 3297static sector_t rs_get_progress(struct raid_set *rs,
3298 sector_t resync_max_sectors, bool *array_in_sync) 3298 sector_t resync_max_sectors, bool *array_in_sync)
3299{ 3299{
3300 sector_t r, recovery_cp, curr_resync_completed; 3300 sector_t r, curr_resync_completed;
3301 struct mddev *mddev = &rs->md; 3301 struct mddev *mddev = &rs->md;
3302 3302
3303 curr_resync_completed = mddev->curr_resync_completed ?: mddev->recovery_cp; 3303 curr_resync_completed = mddev->curr_resync_completed ?: mddev->recovery_cp;
3304 recovery_cp = mddev->recovery_cp;
3305 *array_in_sync = false; 3304 *array_in_sync = false;
3306 3305
3307 if (rs_is_raid0(rs)) { 3306 if (rs_is_raid0(rs)) {
@@ -3330,9 +3329,11 @@ static sector_t rs_get_progress(struct raid_set *rs,
3330 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) 3329 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
3331 r = curr_resync_completed; 3330 r = curr_resync_completed;
3332 else 3331 else
3333 r = recovery_cp; 3332 r = mddev->recovery_cp;
3334 3333
3335 if (r == MaxSector) { 3334 if ((r == MaxSector) ||
3335 (test_bit(MD_RECOVERY_DONE, &mddev->recovery) &&
3336 (mddev->curr_resync_completed == resync_max_sectors))) {
3336 /* 3337 /*
3337 * Sync complete. 3338 * Sync complete.
3338 */ 3339 */
@@ -3892,7 +3893,7 @@ static void raid_resume(struct dm_target *ti)
3892 3893
3893static struct target_type raid_target = { 3894static struct target_type raid_target = {
3894 .name = "raid", 3895 .name = "raid",
3895 .version = {1, 12, 1}, 3896 .version = {1, 13, 0},
3896 .module = THIS_MODULE, 3897 .module = THIS_MODULE,
3897 .ctr = raid_ctr, 3898 .ctr = raid_ctr,
3898 .dtr = raid_dtr, 3899 .dtr = raid_dtr,