]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Create: cleanup after failed create in duplicated array member case
authorDan Williams <dan.j.williams@intel.com>
Mon, 19 Apr 2010 05:28:07 +0000 (15:28 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 19 Apr 2010 05:28:07 +0000 (15:28 +1000)
mdadm prevents creation when device names are duplicated on the command
line, but leaves the partially created array intact.  Detect this case
in the error code from add_to_super() and cleanup the partially created
array.  The imsm handler is updated to report this conflict in
add_to_super_imsm_volume().

Note that since neither mdmon, nor userspace for that matter, ever saw an
active array we only need to perform a subset of the cleanup actions.
So call ioctl(STOP_ARRAY) directly and arrange for Create() to cleanup
the map file rather than calling Manage_runstop().

Reported-by: Krzysztof Wojcik <krzysztof.wojcik@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Create.c
Manage.c
mapfile.c
mdadm.h
super-intel.c

index 8f6e6e7027ae2c9bae263290aa84df667994213d..b04388f5e338205c3136e7ef6ec9a14ea7063a8a 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -789,8 +789,10 @@ int Create(struct supertype *st, char *mddev,
                                if (fd >= 0)
                                        remove_partitions(fd);
                                if (st->ss->add_to_super(st, &inf->disk,
-                                                        fd, dv->devname))
+                                                        fd, dv->devname)) {
+                                       ioctl(mdfd, STOP_ARRAY, NULL);
                                        goto abort;
+                               }
                                st->ss->getinfo_super(st, inf);
                                safe_mode_delay = inf->safe_mode_delay;
 
@@ -894,7 +896,7 @@ int Create(struct supertype *st, char *mddev,
                        if (ioctl(mdfd, RUN_ARRAY, &param)) {
                                fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
                                        strerror(errno));
-                               Manage_runstop(mddev, mdfd, -1, 0);
+                               ioctl(mdfd, STOP_ARRAY, NULL);
                                goto abort;
                        }
                }
@@ -915,6 +917,10 @@ int Create(struct supertype *st, char *mddev,
        return 0;
 
  abort:
+       map_lock(&map);
+       map_remove(&map, fd2devnum(mdfd));
+       map_unlock(&map);
+
        if (mdfd >= 0)
                close(mdfd);
        return 1;
index f848d8b10b4ce536fcafcadf08126ced919ef105..f6fb3ef1875e7d3e29942ad2d1da08b3982f7a3e 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -298,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;
 }
index d47fde1463b8adf9758e9391f58fe79967cc8633..0f12559777b26b0bbbe5c9dbf17ea7dac06e4d54 100644 (file)
--- a/mapfile.c
+++ b/mapfile.c
@@ -251,6 +251,16 @@ void map_delete(struct map_ent **mapp, int devnum)
        }
 }
 
+void map_remove(struct map_ent **mapp, int devnum)
+{
+       if (devnum == NoMdDev)
+               return;
+
+       map_delete(mapp, devnum);
+       map_write(*mapp);
+       map_free(*mapp);
+}
+
 struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4])
 {
        struct map_ent *mp;
diff --git a/mdadm.h b/mdadm.h
index 0386129d62bf7c5ba30ebba52addb9cb17f7590a..1bf5ac0a44de67ad51088d339a1365f5e807450b 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -372,6 +372,7 @@ struct map_ent {
 };
 extern int map_update(struct map_ent **mpp, int devnum, char *metadata,
                      int uuid[4], char *path);
+extern void map_remove(struct map_ent **map, int devnum);
 extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
 extern struct map_ent *map_by_devnum(struct map_ent **map, int devnum);
 extern struct map_ent *map_by_name(struct map_ent **map, char *name);
index 999b9707a37bcb2beed5e99e837fa5ad664c466b..677396c64a9ab2eb953e915a0230299c81941f7e 100644 (file)
@@ -3035,7 +3035,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        map->num_members = info->raid_disks;
        for (i = 0; i < map->num_members; i++) {
                /* initialized in add_to_super */
-               set_imsm_ord_tbl_ent(map, i, 0);
+               set_imsm_ord_tbl_ent(map, i, IMSM_ORD_REBUILD);
        }
        mpb->num_raid_devs++;
 
@@ -3113,6 +3113,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        struct dl *dl;
        struct imsm_dev *dev;
        struct imsm_map *map;
+       int slot;
 
        dev = get_imsm_dev(super, super->current_vol);
        map = get_imsm_map(dev, 0);
@@ -3147,6 +3148,14 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
                dl->index = super->anchor->num_disks;
                super->anchor->num_disks++;
        }
+       /* Check the device has not already been added */
+       slot = get_imsm_disk_slot(map, dl->index);
+       if (slot >= 0 &&
+           (get_imsm_ord_tbl_ent(dev, slot) & IMSM_ORD_REBUILD) == 0) {
+               fprintf(stderr, Name ": %s has been included in this array twice\n",
+                       devname);
+               return 1;
+       }
        set_imsm_ord_tbl_ent(map, dk->number, dl->index);
        dl->disk.status = CONFIGURED_DISK;