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:
parent
efb3994e48
commit
5509dc44d8
40
Manage.c
40
Manage.c
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue