return 0;
}
-/*static */ int is_member_busy(char *metadata_version)
+static int is_member_busy(char *metadata_version)
{
/* check if the given member array is active */
struct mdstat_ent *mdstat = mdstat_read(1, 0);
*/
int mdfd;
int clean;
- int auto_assem = (mddev == NULL);
+ int auto_assem = (mddev == NULL && !ident->uuid_set &&
+ ident->super_minor == UnSet && ident->name[0] == 0
+ && (ident->container == NULL || ident->member == NULL));
int old_linux = 0;
int vers = vers; /* Keep gcc quite - it really is initialised */
struct {
mddev_dev_t tmpdev;
struct mdinfo info;
struct mdinfo *content = NULL;
- mdu_array_info_t tmp_inf;
char *avail;
int nextspare = 0;
char *name = NULL;
fprintf(stderr, Name ": no recogniseable superblock on %s\n",
devname);
tmpdev->used = 2;
+ } else if (auto_assem && st == NULL &&
+ !conf_test_metadata(tst->ss->name)) {
+ if (report_missmatch)
+ fprintf(stderr, Name ": %s has metadata type %s for which "
+ "auto-assembly is disabled\n",
+ devname, tst->ss->name);
+ tmpdev->used = 2;
} else if (tst->ss->load_super(tst,dfd, NULL)) {
if (report_missmatch)
fprintf( stderr, Name ": no RAID superblock on %s\n",
}
if (dfd >= 0) close(dfd);
+ if (tst && tst->sb && tst->ss->container_content
+ && tst->loaded_container) {
+ /* tmpdev is a container. We need to be either
+ * looking for a member, or auto-assembling
+ */
+ if (st) {
+ /* already found some components, this cannot
+ * be another one.
+ */
+ if (report_missmatch)
+ fprintf(stderr, Name ": %s is a container, but we are looking for components\n",
+ devname);
+ goto loop;
+ }
+
+ if (ident->container) {
+ if (ident->container[0] == '/' &&
+ !same_dev(ident->container, devname)) {
+ if (report_missmatch)
+ fprintf(stderr, Name ": %s is not the container required (%s)\n",
+ devname, ident->container);
+ goto loop;
+ }
+ if (ident->container[0] != '/') {
+ /* we have a uuid */
+ int uuid[4];
+ if (!parse_uuid(ident->container, uuid) ||
+ !same_uuid(content->uuid, uuid, tst->ss->swapuuid)) {
+ if (report_missmatch)
+ fprintf(stderr, Name ": %s has wrong UUID to be required container\n",
+ devname);
+ goto loop;
+ }
+ }
+ }
+ /* It is worth looking inside this container.
+ */
+ next_member:
+ if (tmpdev->content)
+ content = tmpdev->content;
+ else
+ content = tst->ss->container_content(tst);
+
+ tmpdev->content = content->next;
+ if (tmpdev->content == NULL)
+ tmpdev->used = 2;
+
+ } else if (ident->container || ident->member) {
+ /* No chance of this matching if we don't have
+ * a container */
+ if (report_missmatch)
+ fprintf(stderr, Name "%s is not a container, and one is required.\n",
+ devname);
+ goto loop;
+ }
+
if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
(!tst || !tst->sb ||
same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0)) {
return 1;
}
+ if (tst && tst->sb && tst->ss->container_content
+ && tst->loaded_container) {
+ /* we have the one container we need, don't keep
+ * looking. If the chosen member is active, skip.
+ */
+ if (is_member_busy(content->text_version)) {
+ if (report_missmatch)
+ fprintf(stderr, Name ": member %s in %s is already assembled\n",
+ content->text_version,
+ devname);
+ tst->ss->free_super(tst);
+ tst = NULL;
+ content = NULL;
+ if (auto_assem)
+ goto loop;
+ return 1;
+ }
+ st = tst; tst = NULL;
+ if (!auto_assem && tmpdev->next != NULL) {
+ fprintf(stderr, Name ": %s is a container, but is not "
+ "only device given: confused and aborting\n",
+ devname);
+ st->ss->free_super(st);
+ return 1;
+ }
+ break;
+ }
if (st == NULL)
st = dup_super(tst);
if (st->minor_version == -1)
tmpdev->used = 1;
loop:
+ if (tmpdev->content)
+ goto next_member;
if (tst)
tst->ss->free_super(tst);
}
if (!st || !st->sb || !content)
return 2;
- /* Now need to open array the device. Use create_mddev */
+ /* Now need to open the array device. Use create_mddev */
if (content == &info)
st->ss->getinfo_super(st, content);
trustworthy = FOREIGN;
- switch (st->ss->match_home(st, homehost)) {
- case 0:
- trustworthy = FOREIGN;
- name = content->name;
- break;
+ name = content->name;
+ switch (st->ss->match_home(st, homehost)
+ ?: st->ss->match_home(st, "any")) {
case 1:
trustworthy = LOCAL;
name = strchr(content->name, ':');
else
name = content->name;
break;
- case -1:
- trustworthy = FOREIGN;
- break;
}
- if (!auto_assem && trustworthy == FOREIGN)
- /* If the array is listed in mdadm or on
+ if (!auto_assem)
+ /* If the array is listed in mdadm.conf or on
* command line, then we trust the name
* even if the array doesn't look local
*/
trustworthy = LOCAL;
- if (content->name[0] == 0 &&
+ if (name[0] == 0 &&
content->array.level == LEVEL_CONTAINER) {
name = content->text_version;
trustworthy = METADATA;
close(mdfd);
return 1;
}
- if (ioctl(mdfd, GET_ARRAY_INFO, &tmp_inf)==0) {
+ if (mddev_busy(fd2devnum(mdfd))) {
fprintf(stderr, Name ": %s already active, cannot restart it!\n",
mddev);
for (tmpdev = devlist ;
}
ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
+#ifndef MDASSEMBLE
+ if (content != &info) {
+ /* This is a member of a container. Try starting the array. */
+ return assemble_container_content(st, mdfd, content, runstop,
+ chosen_name, verbose);
+ }
+#endif
/* Ok, no bad inconsistancy, we can try updating etc */
bitmap_done = 0;
for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
int j = best[i];
if (j>=0 &&
!devices[j].uptodate &&
- devices[j].i.events > 0 &&
(chosen_drive < 0 ||
devices[j].i.events
> devices[chosen_drive].i.events))
int j = best[i];
if (j >= 0 &&
!devices[j].uptodate &&
- devices[j].i.events > 0 &&
devices[j].i.events == current_events) {
chosen_drive = j;
goto add_another;
continue;
devices[j].i.disk.state = desired_state;
+ if (!(devices[j].i.array.state & 1))
+ clean = 0;
if (st->ss->update_super(st, &devices[j].i, "assemble", NULL,
verbose, 0, NULL)) {
fprintf(stderr, "\n");
}
sysfs_uevent(content, "change");
+ wait_for(chosen_name, mdfd);
close(mdfd);
return 0;
}
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
fprintf(stderr, ".\n");
}
+ if (content->reshape_active &&
+ content->array.level >= 4 &&
+ content->array.level <= 6) {
+ /* might need to increase the size
+ * of the stripe cache - default is 256
+ */
+ if (256 < 4 * (content->array.chunk_size/4096)) {
+ struct mdinfo *sra = sysfs_read(mdfd, 0, 0);
+ if (sra)
+ sysfs_set_num(sra, NULL,
+ "stripe_cache_size",
+ (4 * content->array.chunk_size / 4096) + 1);
+ }
+ }
+ wait_for(mddev, mdfd);
close(mdfd);
if (auto_assem) {
int usecs = 1;
}
if (auto_assem)
ioctl(mdfd, STOP_ARRAY, NULL);
+ close(mdfd);
return 1;
} else {
/* The "chosen_drive" is a good choice, and if necessary, the superblock has
sra = sysfs_read(mdfd, 0, GET_VERSION);
if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0)
- if (sysfs_set_array(content, md_get_version(mdfd)) != 0)
+ if (sysfs_set_array(content, md_get_version(mdfd)) != 0) {
+ close(mdfd);
return 1;
+ }
if (sra)
sysfs_free(sra);
for (dev = content->devs; dev; dev = dev->next)
- if (sysfs_add_disk(content, dev) == 0)
+ if (sysfs_add_disk(content, dev, 1) == 0)
working++;
else if (errno == EEXIST)
preexist++;
- if (working == 0)
- /* Nothing new, don't try to start */ ;
- else if (runstop > 0 ||
+ if (working == 0) {
+ close(mdfd);
+ return 1;/* Nothing new, don't try to start */
+ }
+
+ map_update(&map, fd2devnum(mdfd),
+ content->text_version,
+ content->uuid, chosen_name);
+
+ if (runstop > 0 ||
(working + preexist) >= content->array.working_disks) {
+ int err;
+
switch(content->array.level) {
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
case 0:
- sysfs_set_str(content, NULL, "array_state",
- "active");
+ err = sysfs_set_str(content, NULL, "array_state",
+ "active");
break;
default:
- sysfs_set_str(content, NULL, "array_state",
+ err = sysfs_set_str(content, NULL, "array_state",
"readonly");
/* start mdmon if needed. */
- if (!mdmon_running(st->container_dev))
- start_mdmon(st->container_dev);
- ping_monitor(devnum2devname(st->container_dev));
+ if (!err) {
+ if (!mdmon_running(st->container_dev))
+ start_mdmon(st->container_dev);
+ ping_monitor(devnum2devname(st->container_dev));
+ }
break;
}
- sysfs_set_safemode(content, content->safe_mode_delay);
+ if (!err)
+ sysfs_set_safemode(content, content->safe_mode_delay);
if (verbose >= 0) {
- fprintf(stderr, Name
- ": Started %s with %d devices",
- chosen_name, working + preexist);
+ if (err)
+ fprintf(stderr, Name
+ ": array %s now has %d devices",
+ chosen_name, working + preexist);
+ else
+ fprintf(stderr, Name
+ ": Started %s with %d devices",
+ chosen_name, working + preexist);
if (preexist)
fprintf(stderr, " (%d new)", working);
fprintf(stderr, "\n");
}
+ if (!err)
+ wait_for(chosen_name, mdfd);
+ close(mdfd);
+ return 0;
/* FIXME should have an O_EXCL and wait for read-auto */
- } else
+ } else {
if (verbose >= 0)
fprintf(stderr, Name
": %s assembled with %d devices but "
"not started\n",
chosen_name, working);
- map_update(&map, fd2devnum(mdfd),
- content->text_version,
- content->uuid, chosen_name);
-
- return 0;
+ close(mdfd);
+ return 1;
+ }
}
#endif