]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Create: cleanup after failed create in duplicated array member case
[thirdparty/mdadm.git] / Manage.c
index 749fa7c1b8f8b83676e2b5f45c27d83ee2a4666d..f6fb3ef1875e7d3e29942ad2d1da08b3982f7a3e 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -236,11 +236,32 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
                           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 &&
+                                   is_subarray(m->metadata_version+9) &&
+                                   devname2devnum(m->metadata_version+10) == devnum) {
+                                       if (!quiet)
+                                               fprintf(stderr, Name
+                                                       ": Cannot stop container %s: "
+                                                       "member %s still active\n",
+                                                       devname, m->dev);
+                                       free_mdstat(mds);
+                                       if (mdi)
+                                               sysfs_free(mdi);
+                                       return 1;
+                               }
                }
 
                if (fd >= 0 && ioctl(fd, STOP_ARRAY, NULL)) {
@@ -277,11 +298,9 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
 
                if (quiet <= 0)
                        fprintf(stderr, Name ": stopped %s\n", devname);
-               if (devnum != NoMdDev) {
-                       map_delete(&map, devnum);
-                       map_write(map);
-                       map_free(map);
-               }
+               map_lock(&map);
+               map_remove(&map, devnum);
+               map_unlock(&map);
        }
        return 0;
 }
@@ -425,14 +444,22 @@ int Manage_subdevs(char *devname, int fd,
                        j = 0;
 
                        tfd = dev_open(dv->devname, O_RDONLY);
-                       if (tfd < 0 || fstat(tfd, &stb) != 0) {
-                               fprintf(stderr, Name ": cannot find %s: %s\n",
-                                       dv->devname, strerror(errno));
-                               if (tfd >= 0)
-                                       close(tfd);
-                               return 1;
+                       if (tfd < 0 && dv->disposition == 'r' &&
+                           lstat(dv->devname, &stb) == 0)
+                               /* Be happy, the lstat worked, that is
+                                * enough for --remove
+                                */
+                               ;
+                       else {
+                               if (tfd < 0 || fstat(tfd, &stb) != 0) {
+                                       fprintf(stderr, Name ": cannot find %s: %s\n",
+                                               dv->devname, strerror(errno));
+                                       if (tfd >= 0)
+                                               close(tfd);
+                                       return 1;
+                               }
+                               close(tfd);
                        }
-                       close(tfd);
                        if ((stb.st_mode & S_IFMT) != S_IFBLK) {
                                fprintf(stderr, Name ": %s is not a "
                                        "block device.\n",