Commit acb180b0 authored by NeilBrown's avatar NeilBrown

md: improve usefulness and accuracy of sysfs file md/sync_completed.

The sync_completed file reports how much of a resync (or recovery or
reshape) has been completed.
However due to the possibility of out-of-order completion of writes,
it is not certain to be accurate.

We have an internal value - mddev->curr_resync_completed - which is an
accurate value (though it might not always be quite so uptodate).

So:
 - make curr_resync_completed be uptodate a little more often,
   particularly when raid5 reshape updates status in the metadata
 - report curr_resync_completed in the sysfs file
 - allow poll/select to report all updates to md/sync_completed.

This makes sync_completed completed usable by any external metadata
handler that wants to record this status information in its metadata.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent 6d56e278
...@@ -1479,6 +1479,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) ...@@ -1479,6 +1479,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
s += blocks; s += blocks;
} }
bitmap->last_end_sync = jiffies; bitmap->last_end_sync = jiffies;
sysfs_notify(&bitmap->mddev->kobj, NULL, "sync_completed");
} }
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
......
...@@ -2017,6 +2017,8 @@ repeat: ...@@ -2017,6 +2017,8 @@ repeat:
clear_bit(MD_CHANGE_PENDING, &mddev->flags); clear_bit(MD_CHANGE_PENDING, &mddev->flags);
spin_unlock_irq(&mddev->write_lock); spin_unlock_irq(&mddev->write_lock);
wake_up(&mddev->sb_wait); wake_up(&mddev->sb_wait);
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
} }
...@@ -3486,12 +3488,15 @@ sync_completed_show(mddev_t *mddev, char *page) ...@@ -3486,12 +3488,15 @@ sync_completed_show(mddev_t *mddev, char *page)
{ {
unsigned long max_sectors, resync; unsigned long max_sectors, resync;
if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
return sprintf(page, "none\n");
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
max_sectors = mddev->resync_max_sectors; max_sectors = mddev->resync_max_sectors;
else else
max_sectors = mddev->dev_sectors; max_sectors = mddev->dev_sectors;
resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active)); resync = mddev->curr_resync_completed;
return sprintf(page, "%lu / %lu\n", resync, max_sectors); return sprintf(page, "%lu / %lu\n", resync, max_sectors);
} }
...@@ -6338,18 +6343,12 @@ void md_do_sync(mddev_t *mddev) ...@@ -6338,18 +6343,12 @@ void md_do_sync(mddev_t *mddev)
sector_t sectors; sector_t sectors;
skipped = 0; skipped = 0;
if (j >= mddev->resync_max) {
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
wait_event(mddev->recovery_wait,
mddev->resync_max > j
|| kthread_should_stop());
}
if (kthread_should_stop())
goto interrupted;
if (mddev->curr_resync > mddev->curr_resync_completed && if ((mddev->curr_resync > mddev->curr_resync_completed &&
(mddev->curr_resync - mddev->curr_resync_completed) (mddev->curr_resync - mddev->curr_resync_completed)
> (max_sectors >> 4)) { > (max_sectors >> 4)) ||
j >= mddev->resync_max
) {
/* time to update curr_resync_completed */ /* time to update curr_resync_completed */
blk_unplug(mddev->queue); blk_unplug(mddev->queue);
wait_event(mddev->recovery_wait, wait_event(mddev->recovery_wait,
...@@ -6357,7 +6356,17 @@ void md_do_sync(mddev_t *mddev) ...@@ -6357,7 +6356,17 @@ void md_do_sync(mddev_t *mddev)
mddev->curr_resync_completed = mddev->curr_resync_completed =
mddev->curr_resync; mddev->curr_resync;
set_bit(MD_CHANGE_CLEAN, &mddev->flags); set_bit(MD_CHANGE_CLEAN, &mddev->flags);
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
} }
if (j >= mddev->resync_max)
wait_event(mddev->recovery_wait,
mddev->resync_max > j
|| kthread_should_stop());
if (kthread_should_stop())
goto interrupted;
sectors = mddev->pers->sync_request(mddev, j, &skipped, sectors = mddev->pers->sync_request(mddev, j, &skipped,
currspeed < speed_min(mddev)); currspeed < speed_min(mddev));
if (sectors == 0) { if (sectors == 0) {
...@@ -6465,6 +6474,7 @@ void md_do_sync(mddev_t *mddev) ...@@ -6465,6 +6474,7 @@ void md_do_sync(mddev_t *mddev)
skip: skip:
mddev->curr_resync = 0; mddev->curr_resync = 0;
mddev->curr_resync_completed = 0;
mddev->resync_min = 0; mddev->resync_min = 0;
mddev->resync_max = MaxSector; mddev->resync_max = MaxSector;
sysfs_notify(&mddev->kobj, NULL, "sync_completed"); sysfs_notify(&mddev->kobj, NULL, "sync_completed");
......
...@@ -3845,6 +3845,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped ...@@ -3845,6 +3845,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
wait_event(conf->wait_for_overlap, wait_event(conf->wait_for_overlap,
atomic_read(&conf->reshape_stripes)==0); atomic_read(&conf->reshape_stripes)==0);
mddev->reshape_position = conf->reshape_progress; mddev->reshape_position = conf->reshape_progress;
mddev->curr_resync_completed = mddev->curr_resync;
conf->reshape_checkpoint = jiffies; conf->reshape_checkpoint = jiffies;
set_bit(MD_CHANGE_DEVS, &mddev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags);
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
...@@ -3854,6 +3855,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped ...@@ -3854,6 +3855,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
conf->reshape_safe = mddev->reshape_position; conf->reshape_safe = mddev->reshape_position;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
wake_up(&conf->wait_for_overlap); wake_up(&conf->wait_for_overlap);
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
} }
if (mddev->delta_disks < 0) { if (mddev->delta_disks < 0) {
...@@ -3943,6 +3945,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped ...@@ -3943,6 +3945,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
wait_event(conf->wait_for_overlap, wait_event(conf->wait_for_overlap,
atomic_read(&conf->reshape_stripes) == 0); atomic_read(&conf->reshape_stripes) == 0);
mddev->reshape_position = conf->reshape_progress; mddev->reshape_position = conf->reshape_progress;
mddev->curr_resync_completed = mddev->curr_resync;
conf->reshape_checkpoint = jiffies; conf->reshape_checkpoint = jiffies;
set_bit(MD_CHANGE_DEVS, &mddev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags);
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
...@@ -3953,6 +3956,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped ...@@ -3953,6 +3956,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
conf->reshape_safe = mddev->reshape_position; conf->reshape_safe = mddev->reshape_position;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
wake_up(&conf->wait_for_overlap); wake_up(&conf->wait_for_overlap);
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
} }
return reshape_sectors; return reshape_sectors;
} }
......
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