int rv;
int bitmap_fd;
int have_container = 0;
- int container_fd;
+ int container_fd = -1;
int need_mdmon = 0;
unsigned long long bitmapsize;
- struct mdinfo *sra;
struct mdinfo info, *infos;
int did_default = 0;
+ unsigned long safe_mode_delay = 0;
int major_num = BITMAP_MAJOR_HI;
int fd;
memset(&inf, 0, sizeof(inf));
- fd = open(devlist->devname, O_RDONLY, 0);
+ fd = open(devlist->devname, O_RDONLY);
if (fd >= 0 &&
ioctl(fd, GET_ARRAY_INFO, &inf) == 0 &&
inf.raid_disks == 0) {
devlist = NULL;
}
}
+ if (st && st->ss->external && sparedisks) {
+ fprintf(stderr,
+ Name ": This metadata type does not support "
+ "spare disks are create time\n");
+ return 1;
+ }
if (subdevs > raiddisks+sparedisks) {
fprintf(stderr, Name ": You have listed more devices (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
return 1;
minsize = freesize;
}
if (runstop != 1 || verbose >= 0) {
- int fd = open(dname, O_RDONLY, 0);
+ int fd = open(dname, O_RDONLY);
if (fd <0 ) {
fprintf(stderr, Name ": Cannot open %s: %s\n",
dname, strerror(errno));
* into a spare, else the create will fail
*/
if (assume_clean == 0 && force == 0 && first_missing < raiddisks &&
+ st->ss->external == 0 &&
second_missing >= raiddisks && level == 6) {
insert_point = raiddisks - 1;
if (insert_point == first_missing)
( level <= 0 )
||
assume_clean
- )
+ ) {
info.array.state = 1; /* clean, but one+ drive will be missing*/
- else
+ info.resync_start = ~0ULL;
+ } else {
info.array.state = 0; /* not clean, but no errors */
-
+ info.resync_start = 0;
+ }
if (level == 10) {
/* for raid10, the bitmap size is the capacity of the array,
* which is array.size * raid_disks / ncopies;
return 1;
total_slots = info.array.nr_disks;
+ sysfs_init(&info, mdfd, 0);
st->ss->getinfo_super(st, &info);
- if (did_default)
- fprintf(stderr, Name ": Defaulting to version"
- " %s metadata\n", info.text_version);
+ if (did_default && verbose >= 0) {
+ if (is_subarray(info.text_version)) {
+ int dnum = devname2devnum(info.text_version+1);
+ char *path;
+ int mdp = get_mdp_major();
+ struct mdinfo *mdi;
+ if (dnum > 0)
+ path = map_dev(MD_MAJOR, dnum, 1);
+ else
+ path = map_dev(mdp, (-1-dnum)<< 6, 1);
+
+ mdi = sysfs_read(-1, dnum, GET_VERSION);
+
+ fprintf(stderr, Name ": Creating array inside "
+ "%s container %s\n",
+ mdi?mdi->text_version:"managed", path);
+ sysfs_free(mdi);
+ } else
+ fprintf(stderr, Name ": Defaulting to version"
+ " %s metadata\n", info.text_version);
+ }
if (bitmap_file && vers < 9003) {
major_num = BITMAP_MAJOR_HOSTENDIAN;
}
- sra = sysfs_read(mdfd, 0, 0);
+ sysfs_init(&info, mdfd, 0);
- if (st->ss->external) {
- char ver[100];
- strcat(strcpy(ver, "external:"),
- info.text_version);
- if (st->ss->external && st->subarray[0]) {
- /* member */
-
- /* When creating a member, we need to be careful
- * to negotiate with mdmon properly.
- * If it is already running, we cannot write to
- * the devices and must ask it to do that part.
- * If it isn't running, we write to the devices,
- * and then start it.
- * We hold an exclusive open on the container
- * device to make sure mdmon doesn't exit after
- * we checked that it is running.
- *
- * For now, fail if it is already running.
- */
- container_fd = open_dev_excl(st->container_dev);
- if (container_fd < 0) {
- fprintf(stderr, Name ": Cannot get exclusive "
- "open on container - weird.\n");
- return 1;
- }
- if (mdmon_running(st->container_dev)) {
- if (verbose)
- fprintf(stderr, Name ": reusing mdmon "
- "for %s.\n",
- devnum2devname(st->container_dev));
- st->update_tail = &st->updates;
- } else
- need_mdmon = 1;
- }
- if ((vers % 100) < 2 ||
- sra == NULL ||
- sysfs_set_str(sra, NULL, "metadata_version",
- ver) < 0) {
- fprintf(stderr, Name ": This kernel does not "
- "support external metadata.\n");
+ if (st->ss->external && st->subarray[0]) {
+ /* member */
+
+ /* When creating a member, we need to be careful
+ * to negotiate with mdmon properly.
+ * If it is already running, we cannot write to
+ * the devices and must ask it to do that part.
+ * If it isn't running, we write to the devices,
+ * and then start it.
+ * We hold an exclusive open on the container
+ * device to make sure mdmon doesn't exit after
+ * we checked that it is running.
+ *
+ * For now, fail if it is already running.
+ */
+ container_fd = open_dev_excl(st->container_dev);
+ if (container_fd < 0) {
+ fprintf(stderr, Name ": Cannot get exclusive "
+ "open on container - weird.\n");
return 1;
}
- rv = sysfs_set_array(sra, &info);
- } else if ((vers % 100) >= 1) { /* can use different versions */
- mdu_array_info_t inf;
- memset(&inf, 0, sizeof(inf));
- inf.major_version = info.array.major_version;
- inf.minor_version = info.array.minor_version;
- rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
- } else
- rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
+ if (mdmon_running(st->container_dev)) {
+ if (verbose)
+ fprintf(stderr, Name ": reusing mdmon "
+ "for %s.\n",
+ devnum2devname(st->container_dev));
+ st->update_tail = &st->updates;
+ } else
+ need_mdmon = 1;
+ }
+ rv = set_array_info(mdfd, st, &info);
if (rv) {
- fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
+ fprintf(stderr, Name ": failed to set array info for %s: %s\n",
mddev, strerror(errno));
return 1;
}
else
inf->disk.state = 0;
- if (dv->writemostly)
+ if (dv->writemostly == 1)
inf->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
if (st->ss->external && st->subarray[0])
- fd = open(dv->devname, O_RDWR, 0);
+ fd = open(dv->devname, O_RDWR);
else
- fd = open(dv->devname, O_RDWR|O_EXCL,0);
+ fd = open(dv->devname, O_RDWR|O_EXCL);
if (fd < 0) {
fprintf(stderr, Name ": failed to open %s "
st->ss->add_to_super(st, &inf->disk,
fd, dv->devname);
st->ss->getinfo_super(st, inf);
+ safe_mode_delay = inf->safe_mode_delay;
/* getinfo_super might have lost these ... */
inf->disk.major = major(stb.st_rdev);
inf->errors = 0;
rv = 0;
- if (st->ss->external)
- rv = sysfs_add_disk(sra, inf);
- else
- rv = ioctl(mdfd, ADD_NEW_DISK,
- &inf->disk);
+ rv = add_disk(mdfd, st, &info, inf);
if (rv) {
fprintf(stderr,
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
case 0:
- sysfs_set_str(sra, NULL, "array_state",
+ sysfs_set_str(&info, NULL, "array_state",
"active");
need_mdmon = 0;
break;
default:
- sysfs_set_str(sra, NULL, "array_state",
+ sysfs_set_str(&info, NULL, "array_state",
"readonly");
break;
}
+ sysfs_set_safemode(&info, safe_mode_delay);
} else {
mdu_param_t param;
if (ioctl(mdfd, RUN_ARRAY, ¶m)) {
if (verbose >= 0)
fprintf(stderr, Name ": array %s started.\n", mddev);
if (st->ss->external && st->subarray[0]) {
- if (need_mdmon) {
- int dn = st->container_dev;
- int i;
- switch(fork()) {
- case 0:
- /* FIXME yuk. CLOSE_EXEC?? */
- for (i=3; i < 100; i++)
- close(i);
- execl("./mdmon", "mdmon",
- map_dev(dev2major(dn),
- dev2minor(dn),
- 1), NULL);
- exit(1);
- case -1: fprintf(stderr, Name ": cannot fork. "
- "Array remains readonly\n");
- return 1;
- default: ; /* parent - good */
- }
- } else
- signal_mdmon(st->container_dev);
- /* FIXME wait for mdmon to set array to read-auto */
- sleep(1);
+ if (need_mdmon)
+ start_mdmon(st->container_dev);
+
+ ping_monitor(devnum2devname(st->container_dev));
close(container_fd);
}
} else {