summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Incremental.c3
-rw-r--r--Manage.c333
-rw-r--r--mdadm.c12
-rw-r--r--mdadm.h5
4 files changed, 180 insertions, 173 deletions
diff --git a/Incremental.c b/Incremental.c
index ce89702f..fbaa29fe 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1677,8 +1677,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
*/
int devid = devnm2devid(ent->devnm);
run_udisks("--unmount", map_dev(major(devid),minor(devid), 0));
- rv = Manage_runstop(ent->dev, mdfd, -1,
- verbose, 1);
+ rv = Manage_stop(ent->dev, mdfd, verbose, 1);
if (rv)
/* At least we can try to trigger a 'remove' */
sysfs_uevent(&mdi, "remove");
diff --git a/Manage.c b/Manage.c
index 2746149a..be3c652f 100644
--- a/Manage.c
+++ b/Manage.c
@@ -170,21 +170,47 @@ static void remove_devices(char *devnm, char *path)
free(path2);
}
-int Manage_runstop(char *devname, int fd, int runstop,
- int verbose, int will_retry)
+int Manage_run(char *devname, int fd, int verbose)
{
- /* Run or stop the array. Array must already be configured
- * 'Run' requires >= 0.90.0
- * 'will_retry' is only relevant for 'stop', and means
- * that error messages are not wanted.
+ /* Run the array. Array must already be configured
+ * Requires >= 0.90.0
*/
mdu_param_t param; /* unused */
int rv = 0;
+ if (md_get_version(fd) < 9000) {
+ pr_err("need md driver version 0.90.0 or later\n");
+ return 1;
+ }
+
+ if (ioctl(fd, RUN_ARRAY, &param)) {
+ if (verbose >= 0)
+ pr_err("failed to run array %s: %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ if (verbose >= 0)
+ pr_err("started %s\n", devname);
+ return rv;
+}
+
+int Manage_stop(char *devname, int fd, int verbose, int will_retry)
+{
+ /* Stop the array. Array must already be configured
+ * 'will_retry' means that error messages are not wanted.
+ */
+ int rv = 0;
+ struct map_ent *map = NULL;
+ struct mdinfo *mdi;
+ char devnm[32];
+ char container[32];
+ int err;
+ int count;
+
if (will_retry && verbose == 0)
verbose = -1;
- if (runstop == -1 && md_get_version(fd) < 9000) {
+ if (md_get_version(fd) < 9000) {
if (ioctl(fd, STOP_MD, 0) == 0)
return 0;
pr_err("stopping device %s "
@@ -193,185 +219,164 @@ int Manage_runstop(char *devname, int fd, int runstop,
return 1;
}
- if (md_get_version(fd) < 9000) {
- pr_err("need md driver version 0.90.0 or later\n");
- return 1;
+ /* If this is an mdmon managed array, just write 'inactive'
+ * to the array state and let mdmon clear up.
+ */
+ strcpy(devnm, fd2devnm(fd));
+ /* Get EXCL access first. If this fails, then attempting
+ * to stop is probably a bad idea.
+ */
+ mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
+ if (mdi && is_subarray(mdi->text_version)) {
+ char *sl;
+ strncpy(container, mdi->text_version+1, sizeof(container));
+ container[sizeof(container)-1] = 0;
+ sl = strchr(container, '/');
+ if (sl)
+ *sl = 0;
+ } else
+ container[0] = 0;
+ close(fd);
+ count = 5;
+ while (((fd = ((devnm[0] == '/')
+ ?open(devname, O_RDONLY|O_EXCL)
+ :open_dev_flags(devnm, O_RDONLY|O_EXCL))) < 0
+ || strcmp(fd2devnm(fd), devnm) != 0)
+ && container[0]
+ && mdmon_running(container)
+ && count) {
+ if (fd >= 0)
+ close(fd);
+ flush_mdmon(container);
+ count--;
}
-
- if (runstop > 0) {
- if (ioctl(fd, RUN_ARRAY, &param)) {
- if (verbose >= 0)
- pr_err("failed to run array %s: %s\n",
- devname, strerror(errno));
- return 1;
- }
+ if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
+ if (fd >= 0)
+ close(fd);
if (verbose >= 0)
- pr_err("started %s\n", devname);
- } else if (runstop < 0){
- struct map_ent *map = NULL;
- struct mdinfo *mdi;
- char devnm[32];
- char container[32];
+ pr_err("Cannot get exclusive access to %s:"
+ "Perhaps a running "
+ "process, mounted filesystem "
+ "or active volume group?\n",
+ devname);
+ return 1;
+ }
+ if (mdi &&
+ mdi->array.level > 0 &&
+ is_subarray(mdi->text_version)) {
int err;
- int count;
- /* If this is an mdmon managed array, just write 'inactive'
- * to the array state and let mdmon clear up.
- */
- strcpy(devnm, fd2devnm(fd));
- /* Get EXCL access first. If this fails, then attempting
- * to stop is probably a bad idea.
- */
- mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
- if (mdi && is_subarray(mdi->text_version)) {
- char *sl;
- strncpy(container, mdi->text_version+1, sizeof(container));
- container[sizeof(container)-1] = 0;
- sl = strchr(container, '/');
- if (sl)
- *sl = 0;
- } else
- container[0] = 0;
+ /* This is mdmon managed. */
close(fd);
- count = 5;
- while (((fd = ((devnm[0] == '/')
- ?open(devname, O_RDONLY|O_EXCL)
- :open_dev_flags(devnm, O_RDONLY|O_EXCL))) < 0
- || strcmp(fd2devnm(fd), devnm) != 0)
- && container[0]
- && mdmon_running(container)
- && count) {
- if (fd >= 0)
- close(fd);
- flush_mdmon(container);
- count--;
- }
- if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
- if (fd >= 0)
- close(fd);
- if (verbose >= 0)
- pr_err("Cannot get exclusive access to %s:"
- "Perhaps a running "
- "process, mounted filesystem "
- "or active volume group?\n",
- devname);
- return 1;
- }
- if (mdi &&
- mdi->array.level > 0 &&
- is_subarray(mdi->text_version)) {
- int err;
- /* This is mdmon managed. */
- close(fd);
-
- /* As we have an O_EXCL open, any use of the device
- * which blocks STOP_ARRAY is probably a transient use,
- * so it is reasonable to retry for a while - 5 seconds.
- */
- count = 25;
- while (count &&
- (err = sysfs_set_str(mdi, NULL,
- "array_state",
- "inactive")) < 0
- && errno == EBUSY) {
- usleep(200000);
- count--;
- }
- if (err) {
- if (verbose >= 0)
- pr_err("failed to stop array %s: %s\n",
- devname, strerror(errno));
- rv = 1;
- goto out;
- }
-
- /* Give monitor a chance to act */
- ping_monitor(mdi->text_version);
-
- fd = open_dev_excl(devnm);
- if (fd < 0) {
- if (verbose >= 0)
- pr_err("failed to completely stop %s"
- ": Device is busy\n",
- devname);
- rv = 1;
- goto out;
- }
- } else if (mdi &&
- mdi->array.major_version == -1 &&
- mdi->array.minor_version == -2 &&
- !is_subarray(mdi->text_version)) {
- struct mdstat_ent *mds, *m;
- /* container, possibly mdmon-managed.
- * Make sure mdmon isn't opening it, which
- * would interfere with the 'stop'
- */
- ping_monitor(mdi->sys_name);
-
- /* now check that there are no existing arrays
- * which are members of this array
- */
- mds = mdstat_read(0, 0);
- for (m = mds; m; m = m->next)
- if (m->metadata_version &&
- strncmp(m->metadata_version, "external:", 9)==0 &&
- metadata_container_matches(m->metadata_version+9,
- devnm)) {
- if (verbose >= 0)
- pr_err("Cannot stop container %s: "
- "member %s still active\n",
- devname, m->dev);
- free_mdstat(mds);
- rv = 1;
- goto out;
- }
- }
/* As we have an O_EXCL open, any use of the device
* which blocks STOP_ARRAY is probably a transient use,
* so it is reasonable to retry for a while - 5 seconds.
*/
- count = 25; err = 0;
- while (count && fd >= 0
- && (err = ioctl(fd, STOP_ARRAY, NULL)) < 0
+ count = 25;
+ while (count &&
+ (err = sysfs_set_str(mdi, NULL,
+ "array_state",
+ "inactive")) < 0
&& errno == EBUSY) {
usleep(200000);
- count --;
+ count--;
}
- if (fd >= 0 && err) {
- if (verbose >= 0) {
+ if (err) {
+ if (verbose >= 0)
pr_err("failed to stop array %s: %s\n",
devname, strerror(errno));
- if (errno == EBUSY)
- cont_err("Perhaps a running "
- "process, mounted filesystem "
- "or active volume group?\n");
- }
rv = 1;
goto out;
}
- /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array
- * was stopped, so We'll do it here just to be sure. Drop any
- * partitions as well...
+
+ /* Give monitor a chance to act */
+ ping_monitor(mdi->text_version);
+
+ fd = open_dev_excl(devnm);
+ if (fd < 0) {
+ if (verbose >= 0)
+ pr_err("failed to completely stop %s"
+ ": Device is busy\n",
+ devname);
+ rv = 1;
+ goto out;
+ }
+ } else if (mdi &&
+ mdi->array.major_version == -1 &&
+ mdi->array.minor_version == -2 &&
+ !is_subarray(mdi->text_version)) {
+ struct mdstat_ent *mds, *m;
+ /* container, possibly mdmon-managed.
+ * Make sure mdmon isn't opening it, which
+ * would interfere with the 'stop'
*/
- if (fd >= 0)
- ioctl(fd, BLKRRPART, 0);
- if (mdi)
- sysfs_uevent(mdi, "change");
+ ping_monitor(mdi->sys_name);
- if (devnm[0] && use_udev()) {
- struct map_ent *mp = map_by_devnm(&map, devnm);
- remove_devices(devnm, mp ? mp->path : NULL);
+ /* now check that there are no existing arrays
+ * which are members of this array
+ */
+ mds = mdstat_read(0, 0);
+ for (m = mds; m; m = m->next)
+ if (m->metadata_version &&
+ strncmp(m->metadata_version, "external:", 9)==0 &&
+ metadata_container_matches(m->metadata_version+9,
+ devnm)) {
+ if (verbose >= 0)
+ pr_err("Cannot stop container %s: "
+ "member %s still active\n",
+ devname, m->dev);
+ free_mdstat(mds);
+ rv = 1;
+ goto out;
+ }
+ }
+
+ /* As we have an O_EXCL open, any use of the device
+ * which blocks STOP_ARRAY is probably a transient use,
+ * so it is reasonable to retry for a while - 5 seconds.
+ */
+ count = 25; err = 0;
+ while (count && fd >= 0
+ && (err = ioctl(fd, STOP_ARRAY, NULL)) < 0
+ && errno == EBUSY) {
+ usleep(200000);
+ count --;
+ }
+ if (fd >= 0 && err) {
+ if (verbose >= 0) {
+ pr_err("failed to stop array %s: %s\n",
+ devname, strerror(errno));
+ if (errno == EBUSY)
+ cont_err("Perhaps a running "
+ "process, mounted filesystem "
+ "or active volume group?\n");
}
+ rv = 1;
+ goto out;
+ }
+ /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array
+ * was stopped, so We'll do it here just to be sure. Drop any
+ * partitions as well...
+ */
+ if (fd >= 0)
+ ioctl(fd, BLKRRPART, 0);
+ if (mdi)
+ sysfs_uevent(mdi, "change");
- if (verbose >= 0)
- pr_err("stopped %s\n", devname);
- map_lock(&map);
- map_remove(&map, devnm);
- map_unlock(&map);
- out:
- if (mdi)
- sysfs_free(mdi);
+ if (devnm[0] && use_udev()) {
+ struct map_ent *mp = map_by_devnm(&map, devnm);
+ remove_devices(devnm, mp ? mp->path : NULL);
}
+
+ if (verbose >= 0)
+ pr_err("stopped %s\n", devname);
+ map_lock(&map);
+ map_remove(&map, devnm);
+ map_unlock(&map);
+out:
+ if (mdi)
+ sysfs_free(mdi);
+
return rv;
}
diff --git a/mdadm.c b/mdadm.c
index 928d880b..fe6c2fa8 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1301,8 +1301,10 @@ int main(int argc, char *argv[])
c.update, c.force);
if (!rv && c.readonly < 0)
rv = Manage_ro(devlist->devname, mdfd, c.readonly);
- if (!rv && c.runstop)
- rv = Manage_runstop(devlist->devname, mdfd, c.runstop, c.verbose, 0);
+ if (!rv && c.runstop > 0)
+ rv = Manage_run(devlist->devname, mdfd, c.verbose);
+ if (!rv && c.runstop < 0)
+ rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0);
break;
case ASSEMBLE:
if (devs_found == 1 && ident.uuid_set == 0 &&
@@ -1727,7 +1729,7 @@ static int stop_scan(int verbose)
}
mdfd = open_mddev(name, 1);
if (mdfd >= 0) {
- if (Manage_runstop(name, mdfd, -1, verbose, !last))
+ if (Manage_stop(name, mdfd, verbose, !last))
err = 1;
else
progress = 1;
@@ -1805,9 +1807,9 @@ static int misc_list(struct mddev_dev *devlist,
if (mdfd>=0) {
switch(dv->disposition) {
case 'R':
- rv |= Manage_runstop(dv->devname, mdfd, 1, c->verbose, 0); break;
+ rv |= Manage_run(dv->devname, mdfd, c->verbose); break;
case 'S':
- rv |= Manage_runstop(dv->devname, mdfd, -1, c->verbose, 0); break;
+ rv |= Manage_stop(dv->devname, mdfd, c->verbose, 0); break;
case 'o':
rv |= Manage_ro(dv->devname, mdfd, 1); break;
case 'w':
diff --git a/mdadm.h b/mdadm.h
index c83a85cb..f498b937 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1158,8 +1158,9 @@ extern int add_dev(const char *name, const struct stat *stb, int flag, struct FT
extern int Manage_ro(char *devname, int fd, int readonly);
-extern int Manage_runstop(char *devname, int fd, int runstop, int quiet,
- int will_retry);
+extern int Manage_run(char *devname, int fd, int quiet);
+extern int Manage_stop(char *devname, int fd, int quiet,
+ int will_retry);
extern int Manage_subdevs(char *devname, int fd,
struct mddev_dev *devlist, int verbose, int test,
char *update, int force);