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.2.orig/Assemble.c +++ mdadm-3.2.2/Assemble.c @@ -233,6 +233,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; @@ -680,9 +681,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; @@ -694,6 +699,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))) { @@ -707,6 +713,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) @@ -723,6 +730,7 @@ int Assemble(struct supertype *st, char chosen_name, verbose, backup_file, freeze_reshape); close(mdfd); + map_unlock(&map); return err; } #endif @@ -764,6 +772,7 @@ int Assemble(struct supertype *st, char if (dfd >= 0) close(dfd); close(mdfd); + map_unlock(&map); free(devices); free(devmap); return 1; @@ -789,6 +798,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); @@ -827,6 +837,7 @@ int Assemble(struct supertype *st, char if (dfd >= 0) close(dfd); close(mdfd); + map_unlock(&map); free(devices); free(devmap); return 1; @@ -901,6 +912,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; @@ -919,6 +931,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; @@ -1088,6 +1101,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; } @@ -1096,6 +1110,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; } @@ -1104,6 +1119,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; } @@ -1168,6 +1184,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; } @@ -1176,6 +1193,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; } @@ -1233,6 +1251,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; } @@ -1250,7 +1269,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); @@ -1259,6 +1278,7 @@ int Assemble(struct supertype *st, char mddev, strerror(errno)); ioctl(mdfd, STOP_ARRAY, NULL); close(mdfd); + map_unlock(&map); free(devices); return 1; } @@ -1267,6 +1287,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; } @@ -1278,6 +1299,7 @@ int Assemble(struct supertype *st, char ident->bitmap_file); ioctl(mdfd, STOP_ARRAY, NULL); close(mdfd); + map_unlock(&map); free(devices); return 1; } @@ -1286,6 +1308,7 @@ int Assemble(struct supertype *st, char close(bmfd); ioctl(mdfd, STOP_ARRAY, NULL); close(mdfd); + map_unlock(&map); free(devices); return 1; } @@ -1347,6 +1370,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; } @@ -1427,6 +1451,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'. @@ -1474,6 +1499,7 @@ int Assemble(struct supertype *st, char if (auto_assem) ioctl(mdfd, STOP_ARRAY, NULL); close(mdfd); + map_unlock(&map); free(devices); return 1; } @@ -1484,6 +1510,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; } @@ -1514,6 +1541,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 { @@ -1531,6 +1559,7 @@ int Assemble(struct supertype *st, char } close(mdfd); + map_unlock(&map); free(devices); return 0; }