File Restructure-assemble_container_content-and-improve-m.patch of Package mdadm.2874
From c1736844ba49ec1a8731b5815abfd6530b982a3b Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 28 Nov 2013 14:47:41 +1100
Subject: [PATCH 1/2] Restructure assemble_container_content and  improve
 messages.
We lose one level of indent, and now get told the difference between
'not assemble because not safe' and 'not assembled because not enough
devices'.
Signed-off-by: NeilBrown <neilb@suse.de>
---
 Assemble.c | 176 ++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 99 insertions(+), 77 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 4d5ceeac8674..11b77c288608 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1779,6 +1779,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
 	struct map_ent *map = NULL;
 	int old_raid_disks;
 	int start_reshape;
+	char *avail = NULL;
+	int err;
 
 	sysfs_init(content, mdfd, NULL);
 
@@ -1812,7 +1814,10 @@ int assemble_container_content(struct supertype *st, int mdfd,
 	if (sra)
 		sysfs_free(sra);
 	old_raid_disks = content->array.raid_disks - content->delta_disks;
-	for (dev = content->devs; dev; dev = dev->next)
+	avail = xcalloc(content->array.raid_disks, 1);
+	for (dev = content->devs; dev; dev = dev->next) {
+		if (dev->disk.raid_disk >= 0)
+			avail[dev->disk.raid_disk] = 1;
 		if (sysfs_add_disk(content, dev, 1) == 0) {
 			if (dev->disk.raid_disk >= old_raid_disks &&
 			    content->reshape_active)
@@ -1821,100 +1826,117 @@ int assemble_container_content(struct supertype *st, int mdfd,
 				working++;
 		} else if (errno == EEXIST)
 			preexist++;
-	if (working + expansion == 0 && c->runstop <= 0)
+	}
+	if (working + expansion == 0 && c->runstop <= 0) {
+		free(avail);
 		return 1;/* Nothing new, don't try to start */
-
+	}
 	map_update(&map, fd2devnm(mdfd),
 		   content->text_version,
 		   content->uuid, chosen_name);
 
-	if (c->runstop > 0 ||
-	    (working + preexist + expansion) >=
-	    content->array.working_disks) {
-		int err;
-
-		if (start_reshape) {
-			int spare = content->array.raid_disks + expansion;
-			if (restore_backup(st, content,
-					   working,
-					   spare, c->backup_file, c->verbose) == 1)
-				return 1;
-
-			err = sysfs_set_str(content, NULL,
-					    "array_state", "readonly");
-			if (err)
-				return 1;
-
-			if (st->ss->external) {
-				if (!mdmon_running(st->container_devnm))
-					start_mdmon(st->container_devnm);
-				ping_monitor(st->container_devnm);
-				if (mdmon_running(st->container_devnm) &&
-				    st->update_tail == NULL)
-					st->update_tail = &st->updates;
-			}
-
-			err = Grow_continue(mdfd, st, content, c->backup_file,
-					    c->freeze_reshape);
-		} else switch(content->array.level) {
-			case LEVEL_LINEAR:
-			case LEVEL_MULTIPATH:
-			case 0:
-				err = sysfs_set_str(content, NULL, "array_state",
-						    c->readonly ? "readonly" : "active");
-				break;
-			default:
-				err = sysfs_set_str(content, NULL, "array_state",
-						    "readonly");
-				/* start mdmon if needed. */
-				if (!err) {
-					if (!mdmon_running(st->container_devnm))
-						start_mdmon(st->container_devnm);
-					ping_monitor(st->container_devnm);
-				}
-				break;
-			}
-		if (!err)
-			sysfs_set_safemode(content, content->safe_mode_delay);
-
-		/* Block subarray here if it is not reshaped now
-		 * It has be blocked a little later to allow mdmon to switch in
-		 * in to R/W state
-		 */
-		if (st->ss->external && content->recovery_blocked &&
-		    !start_reshape)
-			block_subarray(content);
 
+	if (enough(content->array.level, content->array.raid_disks,
+		   content->array.layout, content->array.state & 1, avail) == 0) {
 		if (c->verbose >= 0) {
-			if (err)
-				pr_err("array %s now has %d device%s",
-				       chosen_name, working + preexist,
-				       working + preexist == 1 ? "":"s");
-			else
-				pr_err("Started %s with %d device%s",
-				       chosen_name, working + preexist,
-				       working + preexist == 1 ? "":"s");
+			pr_err("%s assembled with %d device%s",
+			       chosen_name, preexist + working,
+			       preexist + working == 1 ? "":"s");
 			if (preexist)
 				fprintf(stderr, " (%d new)", working);
-			if (expansion)
-				fprintf(stderr, " ( + %d for expansion)",
-					expansion);
-			fprintf(stderr, "\n");
+			fprintf(stderr, " but not started\n");
 		}
-		if (!err)
-			wait_for(chosen_name, mdfd);
-		return err;
-		/* FIXME should have an O_EXCL and wait for read-auto */
-	} else {
+		free(avail);
+		return 1;
+	}
+	free(avail);
+
+	if (c->runstop <= 0 &&
+	    (working + preexist + expansion) <
+	    content->array.working_disks) {
 		if (c->verbose >= 0) {
 			pr_err("%s assembled with %d device%s",
 			       chosen_name, preexist + working,
 			       preexist + working == 1 ? "":"s");
 			if (preexist)
 				fprintf(stderr, " (%d new)", working);
-			fprintf(stderr, " but not started\n");
+			fprintf(stderr, " but not safe to start\n");
 		}
 		return 1;
 	}
+
+
+	if (start_reshape) {
+		int spare = content->array.raid_disks + expansion;
+		if (restore_backup(st, content,
+				   working,
+				   spare, c->backup_file, c->verbose) == 1)
+			return 1;
+
+		err = sysfs_set_str(content, NULL,
+				    "array_state", "readonly");
+		if (err)
+			return 1;
+
+		if (st->ss->external) {
+			if (!mdmon_running(st->container_devnm))
+				start_mdmon(st->container_devnm);
+			ping_monitor(st->container_devnm);
+			if (mdmon_running(st->container_devnm) &&
+			    st->update_tail == NULL)
+				st->update_tail = &st->updates;
+		}
+
+		err = Grow_continue(mdfd, st, content, c->backup_file,
+				    c->freeze_reshape);
+	} else switch(content->array.level) {
+		case LEVEL_LINEAR:
+		case LEVEL_MULTIPATH:
+		case 0:
+			err = sysfs_set_str(content, NULL, "array_state",
+					    c->readonly ? "readonly" : "active");
+			break;
+		default:
+			err = sysfs_set_str(content, NULL, "array_state",
+					    "readonly");
+			/* start mdmon if needed. */
+			if (!err) {
+				if (!mdmon_running(st->container_devnm))
+					start_mdmon(st->container_devnm);
+				ping_monitor(st->container_devnm);
+			}
+			break;
+		}
+	if (!err)
+		sysfs_set_safemode(content, content->safe_mode_delay);
+
+	/* Block subarray here if it is not reshaped now
+	 * It has be blocked a little later to allow mdmon to switch in
+	 * in to R/W state
+	 */
+	if (st->ss->external && content->recovery_blocked &&
+	    !start_reshape)
+		block_subarray(content);
+
+	if (c->verbose >= 0) {
+		if (err)
+			pr_err("array %s now has %d device%s",
+			       chosen_name, working + preexist,
+			       working + preexist == 1 ? "":"s");
+		else
+			pr_err("Started %s with %d device%s",
+			       chosen_name, working + preexist,
+			       working + preexist == 1 ? "":"s");
+		if (preexist)
+			fprintf(stderr, " (%d new)", working);
+		if (expansion)
+			fprintf(stderr, " ( + %d for expansion)",
+				expansion);
+		fprintf(stderr, "\n");
+	}
+	if (!err)
+		wait_for(chosen_name, mdfd);
+	return err;
+	/* FIXME should have an O_EXCL and wait for read-auto */
 }
 #endif
-- 
1.8.3.1.487.g3e7a5b4