- 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;
- }
- }