#include "mdadm.h"
+static int name_matches(char *found, char *required, char *homehost)
+{
+ /* See if the name found matches the required name, possibly
+ * prefixed with 'homehost'
+ */
+ char fnd[33];
+
+ strncpy(fnd, found, 32);
+ fnd[32] = 0;
+ if (strcmp(found, required)==0)
+ return 1;
+ if (homehost) {
+ int l = strlen(homehost);
+ if (l < 32 && fnd[l] == ':' &&
+ strcmp(fnd+l+1, required)==0)
+ return 1;
+ }
+ return 0;
+}
+
int Assemble(struct supertype *st, char *mddev, int mdfd,
mddev_ident_t ident, char *conffile,
mddev_dev_t devlist, char *backup_file,
fprintf(stderr, Name ": looking for devices for %s\n",
mddev);
- while ( devlist) {
- char *devname;
+ /* first walk the list of devices to find a consistent set
+ * that match the criterea, if that is possible.
+ * We flag the one we like with 'used'.
+ */
+ for (tmpdev = devlist;
+ tmpdev;
+ tmpdev = tmpdev->next) {
+ char *devname = tmpdev->devname;
int dfd;
struct stat stb;
struct supertype *tst = st;
- devname = devlist->devname;
- devlist = devlist->next;
-
if (ident->devices &&
!match_oneof(ident->devices, devname)) {
if ((inargv && verbose>=0) || verbose > 0)
continue;
}
if (ident->name[0] && (!update || strcmp(update, "name")!= 0) &&
- (!super || strncmp(info.name, ident->name, 32)!=0)) {
+ (!super || name_matches(info.name, ident->name, homehost)==0)) {
if ((inargv && verbose >= 0) || verbose > 0)
fprintf(stderr, Name ": %s has wrong name.\n",
devname);
continue;
}
- /* If we are this far, then we are commited to this device.
+ /* If we are this far, then we are nearly commited to this device.
* If the super_block doesn't exist, or doesn't match others,
- * then we cannot continue
+ * then we probably cannot continue
+ * However if one of the arrays is for the homehost, and
+ * the other isn't that can disambiguate.
*/
if (!super) {
return 1;
}
-
- st = tst; /* commit to this format, if haven't already */
- if (st->ss->compare_super(&first_super, super)) {
+ if (st == NULL)
+ st = tst;
+ if (st->ss != tst->ss ||
+ st->minor_version != tst->minor_version ||
+ st->ss->compare_super(&first_super, super) != 0) {
+ /* Some mismatch. If exactly one array matches this host,
+ * we can resolve on that one
+ */
+ if (homehost) {
+ int first = st->ss->match_home(first_super, homehost);
+ int last = tst->ss->match_home(super, homehost);
+ if (first+last == 1) {
+ /* We can do something */
+ if (first) {/* just ignore this one */
+ if ((inargv && verbose >= 0) || verbose > 0)
+ fprintf(stderr, Name ": %s misses out due to wrong homehost\n",
+ devname);
+ continue;
+ } else { /* reject all those sofar */
+ mddev_dev_t td;
+ if ((inargv && verbose >= 0) || verbose > 0)
+ fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n",
+ devname);
+ for (td=devlist; td != tmpdev; td=td->next)
+ if (td->used == 1)
+ td->used = 0;
+ tmpdev->used = 1;
+ continue;
+ }
+ }
+ }
fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
devname);
free(super);
return 1;
}
+ tmpdev->used = 1;
+ }
+
+ /* Ok, no bad inconsistancy, we can try updating etc */
+ for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used) {
+ char *devname = tmpdev->devname;
+ struct stat stb;
/* looks like a good enough match to update the super block if needed */
if (update) {
+ int dfd;
/* prepare useful information in info structures */
struct stat stb2;
fstat(mdfd, &stb2);
- info.array.md_minor = minor(stb2.st_rdev);
if (strcmp(update, "uuid")==0 &&
!ident->uuid_set) {
}
if (rfd >= 0) close(rfd);
}
+ dfd = dev_open(devname, O_RDWR|O_EXCL);
+
+ if (super) {
+ free(super);
+ super = NULL;
+ }
+
+ st->ss->load_super(st, dfd, &super, NULL);
+ st->ss->getinfo_super(&info, super);
+
memcpy(info.uuid, ident->uuid, 16);
strcpy(info.name, ident->name);
+ info.array.md_minor = minor(stb2.st_rdev);
+
st->ss->update_super(&info, super, update, devname, verbose,
ident->uuid_set, homehost);
if (strcmp(update, "uuid")==0 &&
ident->uuid_set = 1;
memcpy(ident->uuid, info.uuid, 16);
}
- dfd = dev_open(devname, O_RDWR|O_EXCL);
if (dfd < 0)
fprintf(stderr, Name ": Cannot open %s for superblock update\n",
devname);
bitmap_update_uuid(ident->bitmap_fd, info.uuid);
}
+ stat(devname, &stb);
+
if (verbose > 0)
fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
devname, mddev, info.disk.raid_disk);