Dan Williams: Create: cleanup after failed create in duplicated array member case

Martin F. Krafft madduck at alioth.debian.org
Sat Aug 28 18:44:04 UTC 2010


Module: mdadm
Branch: build
Commit: 4eb269706f403d2424166683688f0a41d893c1c3
URL:    http://git.debian.org/?p=pkg-mdadm/mdadm.git;a=commit;h=4eb269706f403d2424166683688f0a41d893c1c3

Author: Dan Williams <dan.j.williams at intel.com>
Date:   Mon Apr 19 15:28:07 2010 +1000

Create: cleanup after failed create in duplicated array member case

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 at intel.com>
Signed-off-by: Dan Williams <dan.j.williams at intel.com>

---

 Create.c      |   10 ++++++++--
 Manage.c      |    8 +++-----
 mapfile.c     |   10 ++++++++++
 mdadm.h       |    1 +
 super-intel.c |   11 ++++++++++-
 5 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/Create.c b/Create.c
index 8f6e6e7..b04388f 100644
--- 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;
diff --git a/Manage.c b/Manage.c
index f848d8b..f6fb3ef 100644
--- 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;
 }
diff --git a/mapfile.c b/mapfile.c
index d47fde1..0f12559 100644
--- 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 0386129..1bf5ac0 100644
--- 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);
diff --git a/super-intel.c b/super-intel.c
index 999b970..677396c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -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;
 




More information about the pkg-mdadm-commits mailing list