Stop: improve synchronising of reshape with whole stripes.

It is possible for 'sync_completed' to be further ahead than
we deduced from 'reshape_position'.  However we cannot read it while
the array is frozen, so it is hard to know.

Once that array is unfrozen, check and if sync_completed is ahead of
'sync_max',  push 'sync_max' well ahead if 'sync_completed' so it
will all synchronise up properly.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2013-07-02 16:18:21 +10:00
parent efb3994e48
commit 5509dc44d8
1 changed files with 30 additions and 10 deletions

View File

@ -357,6 +357,8 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
unsigned long long chunk1, chunk2;
unsigned long long rddiv, chunkdiv;
unsigned long long sectors;
unsigned long long sync_max, old_sync_max;
unsigned long long completed;
int backwards = 0;
int delay;
int scfd;
@ -383,28 +385,46 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
size &= ~(chunk1-1);
size &= ~(chunk2-1);
/* rd1 must be smaller */
size *= rd1;
position = size - position;
position = (position/sectors + 2) * sectors;
sysfs_set_num(mdi, NULL, "sync_max", position/rd1);
position = size - position;
position = (position / sectors - 1) * sectors;
sync_max = size - position/rd1;
} else {
position = (position/sectors + 2) * sectors;
sysfs_set_num(mdi, NULL, "sync_max", position/rd1);
position = (position / sectors + 2) * sectors;
sync_max = position/rd1;
}
if (sysfs_get_ll(mdi, NULL, "sync_max", &old_sync_max) < 0)
old_sync_max = mdi->component_size;
/* Must not advance sync_max as that could confuse
* the reshape monitor */
if (sync_max < old_sync_max)
sysfs_set_num(mdi, NULL, "sync_max", sync_max);
sysfs_set_str(mdi, NULL, "sync_action", "idle");
/* That should have set things going again. Now we
* wait a little while (5 seconds) for sync_completed
* wait a little while (1 second max) for sync_completed
* to reach the target.
*/
delay = 500;
delay = 1000;
scfd = sysfs_open(mdi->sys_name, NULL, "sync_completed");
while (scfd >= 0 && delay > 0) {
sysfs_get_ll(mdi, NULL, "reshape_position", &curr);
sysfs_fd_get_str(scfd, buf, sizeof(buf));
if (strncmp(buf, "none", 4) == 0)
break;
sysfs_get_ll(mdi, NULL, "reshape_position", &curr);
if (sysfs_fd_get_ll(scfd, &completed) == 0 &&
(completed > sync_max ||
(completed == sync_max && curr != position))) {
while (completed > sync_max) {
sync_max += sectors / rd1;
if (backwards)
position -= sectors;
else
position += sectors;
}
if (sync_max < old_sync_max)
sysfs_set_num(mdi, NULL, "sync_max", sync_max);
}
if (!backwards && curr >= position)
break;
if (backwards && curr <= position)