Stop managed arrays more carefully.

If an array is being managed by mdmon, then just
write "inactive" to stop it, and let mdmon do the
final "clear".  This makes sure mdmon has a chance
to read the final state and update the metadata properly.

After writing "inactive" with use "ping_monitor" to synchronise
with mdadm, then STOP the array just in case it is still running,
else we will get into an infinite loop in "mdadm -Ss".

Signed-off-by: Neil Brown <neilb@suse.de>
This commit is contained in:
Neil Brown 2008-07-18 16:37:09 +10:00
parent 1eb252b848
commit daf7a3ce96
2 changed files with 37 additions and 13 deletions

View File

@ -111,15 +111,49 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
} else if (runstop < 0){
struct map_ent *map = NULL;
struct stat stb;
if (ioctl(fd, STOP_ARRAY, NULL)) {
struct mdinfo *mdi;
/* If this is an mdmon managed array, just write 'inactive'
* to the array state and let mdmon clear up.
*/
mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION);
if (mdi &&
mdi->array.level > 0 &&
mdi->text_version[0] == '/') {
char *cp;
/* This is mdmon managed. */
close(fd);
if (sysfs_set_str(mdi, NULL,
"array_state", "inactive") < 0) {
if (quiet==0)
fprintf(stderr, Name
": fail to stop array %s: %s\n",
devname, strerror(errno));
return 1;
}
/* Give monitor a chance to act */
cp = strchr(mdi->text_version+1, '/');
if (*cp)
*cp = 0;
ping_monitor(mdi->text_version+1);
fd = open(devname, O_RDONLY);
}
if (mdi)
sysfs_free(mdi);
if (fd >= 0 && ioctl(fd, STOP_ARRAY, NULL)) {
if (quiet==0)
fprintf(stderr, Name ": fail to stop array %s: %s\n",
fprintf(stderr, Name
": fail to stop array %s: %s\n",
devname, strerror(errno));
return 1;
}
if (quiet <= 0)
fprintf(stderr, Name ": stopped %s\n", devname);
if (fstat(fd, &stb) == 0) {
if (fd >= 0 && fstat(fd, &stb) == 0) {
int devnum;
if (major(stb.st_rdev) == MD_MAJOR)
devnum = minor(stb.st_rdev);

10
mdadm.c
View File

@ -1257,16 +1257,6 @@ int main(int argc, char *argv[])
put_md_name(name);
}
/* This is a bit of a hack.
* When we stop an array in a container, it
* takes a moment for mdmon to let go.
* So just pause briefly incase that is
* happening. Maybe we should do something
* more deterministic via the socket.
*/
if (progress && err)
usleep(50000);
} while (!last && err);
if (err) rv |= 1;
} else {