Subject: take the map lock will assembling an array.
References:  bnc#790732

This ensures that two separate mdadm instances don't both
try to use the same free md device.
Incremental and Create already hold the lock so only Assemble needs it.


---
 Assemble.c |   31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

--- mdadm-3.2.6.orig/Assemble.c
+++ mdadm-3.2.6/Assemble.c
@@ -235,6 +235,7 @@ int Assemble(struct supertype *st, char
 	int trustworthy;
 	char chosen_name[1024];
 	struct domainlist *domains = NULL;
+	struct map_ent *map = NULL;
 
 	if (get_linux_version() < 2004000)
 		old_linux = 1;
@@ -683,9 +684,13 @@ int Assemble(struct supertype *st, char
 		/* Ignore 'host:' prefix of name */
 		name = strchr(name, ':')+1;
 
+	if (map_lock(&map))
+		fprintf(stderr, Name ": failed to get exclusive lock on mapfile - continuing anyway...\n");
+
 	mdfd = create_mddev(mddev, name, ident->autof, trustworthy,
 			    chosen_name);
 	if (mdfd < 0) {
+		map_unlock(&map);
 		st->ss->free_super(st);
 		if (auto_assem)
 			goto try_again;
@@ -697,6 +702,7 @@ int Assemble(struct supertype *st, char
 		fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
 			"    Upgrade your kernel or try --build\n");
 		close(mdfd);
+		map_unlock(&map);
 		return 1;
 	}
 	if (mddev_busy(fd2devnum(mdfd))) {
@@ -710,6 +716,7 @@ int Assemble(struct supertype *st, char
 			fprintf(stderr, Name ":   %s needed for %s...\n",
 				mddev, tmpdev->devname);
 		close(mdfd);
+		map_unlock(&map);
 		mdfd = -3;
 		st->ss->free_super(st);
 		if (auto_assem)
@@ -726,6 +733,7 @@ int Assemble(struct supertype *st, char
 						 chosen_name, verbose,
 						 backup_file, freeze_reshape);
 		close(mdfd);
+		map_unlock(&map);
 		return err;
 	}
 	bitmap_done = 0;
@@ -767,6 +775,7 @@ int Assemble(struct supertype *st, char
 				if (dfd >= 0)
 					close(dfd);
 				close(mdfd);
+				map_unlock(&map);
 				free(devices);
 				free(devmap);
 				return 1;
@@ -792,6 +801,7 @@ int Assemble(struct supertype *st, char
 				tst->ss->free_super(tst);
 				free(tst);
 				close(mdfd);
+				map_unlock(&map);
 				close(dfd);
 				free(devices);
 				free(devmap);
@@ -830,6 +840,7 @@ int Assemble(struct supertype *st, char
 				if (dfd >= 0)
 					close(dfd);
 				close(mdfd);
+				map_unlock(&map);
 				free(devices);
 				free(devmap);
 				return 1;
@@ -904,6 +915,7 @@ int Assemble(struct supertype *st, char
 					   "the\n      DEVICE list in mdadm.conf"
 					);
 				close(mdfd);
+				map_unlock(&map);
 				free(devices);
 				free(devmap);
 				return 1;
@@ -922,6 +934,7 @@ int Assemble(struct supertype *st, char
 		if (st)
 			st->ss->free_super(st);
 		close(mdfd);
+		map_unlock(&map);
 		free(devices);
 		free(devmap);
 		return 1;
@@ -1102,6 +1115,7 @@ int Assemble(struct supertype *st, char
 			fprintf(stderr, Name ": Cannot open %s: %s\n",
 				devices[j].devname, strerror(errno));
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 1;
 		}
@@ -1110,6 +1124,7 @@ int Assemble(struct supertype *st, char
 			fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
 				devices[j].devname);
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 1;
 		}
@@ -1118,6 +1133,7 @@ int Assemble(struct supertype *st, char
 	if (st->sb == NULL) {
 		fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
 		close(mdfd);
+		map_unlock(&map);
 		free(devices);
 		return 1;
 	}
@@ -1182,6 +1198,7 @@ int Assemble(struct supertype *st, char
 			fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n",
 				devices[chosen_drive].devname);
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 1;
 		}
@@ -1190,6 +1207,7 @@ int Assemble(struct supertype *st, char
 			fprintf(stderr, Name ": Could not re-write superblock on %s\n",
 				devices[chosen_drive].devname);
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 1;
 		}
@@ -1247,6 +1265,7 @@ int Assemble(struct supertype *st, char
 			if (backup_file == NULL)
 				fprintf(stderr,"      Possibly you needed to specify the --backup-file\n");
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return err;
 		}
@@ -1264,7 +1283,7 @@ int Assemble(struct supertype *st, char
 		/* First, fill in the map, so that udev can find our name
 		 * as soon as we become active.
 		 */
-		map_update(NULL, fd2devnum(mdfd), content->text_version,
+		map_update(&map, fd2devnum(mdfd), content->text_version,
 			   content->uuid, chosen_name);
 
 		rv = set_array_info(mdfd, st, content);
@@ -1273,6 +1292,7 @@ int Assemble(struct supertype *st, char
 				mddev, strerror(errno));
 			ioctl(mdfd, STOP_ARRAY, NULL);
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 1;
 		}
@@ -1281,6 +1301,7 @@ int Assemble(struct supertype *st, char
 				fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n");
 				ioctl(mdfd, STOP_ARRAY, NULL);
 				close(mdfd);
+				map_unlock(&map);
 				free(devices);
 				return 1;
 			}
@@ -1292,6 +1313,7 @@ int Assemble(struct supertype *st, char
 					ident->bitmap_file);
 				ioctl(mdfd, STOP_ARRAY, NULL);
 				close(mdfd);
+				map_unlock(&map);
 				free(devices);
 				return 1;
 			}
@@ -1300,6 +1322,7 @@ int Assemble(struct supertype *st, char
 				close(bmfd);
 				ioctl(mdfd, STOP_ARRAY, NULL);
 				close(mdfd);
+				map_unlock(&map);
 				free(devices);
 				return 1;
 			}
@@ -1363,6 +1386,7 @@ int Assemble(struct supertype *st, char
 			sysfs_uevent(content, "change");
 			wait_for(chosen_name, mdfd);
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 0;
 		}
@@ -1443,6 +1467,7 @@ int Assemble(struct supertype *st, char
 				}
 				wait_for(mddev, mdfd);
 				close(mdfd);
+				map_unlock(&map);
 				if (auto_assem) {
 					int usecs = 1;
 					/* There is a nasty race with 'mdadm --monitor'.
@@ -1490,6 +1515,7 @@ int Assemble(struct supertype *st, char
 			if (auto_assem)
 				ioctl(mdfd, STOP_ARRAY, NULL);
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 1;
 		}
@@ -1500,6 +1526,7 @@ int Assemble(struct supertype *st, char
 				fprintf(stderr, " (out of %d)", content->array.raid_disks);
 			fprintf(stderr, ", but not started.\n");
 			close(mdfd);
+			map_unlock(&map);
 			free(devices);
 			return 0;
 		}
@@ -1530,6 +1557,7 @@ int Assemble(struct supertype *st, char
 		if (auto_assem)
 			ioctl(mdfd, STOP_ARRAY, NULL);
 		close(mdfd);
+		map_unlock(&map);
 		free(devices);
 		return 1;
 	} else {
@@ -1547,6 +1575,7 @@ int Assemble(struct supertype *st, char
 
 	}
 	close(mdfd);
+	map_unlock(&map);
 	free(devices);
 	return 0;
 }
