X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Create.c;h=68a423014786e7e74d23b30fb1d8a78744f0b7b1;hb=f4d11639d1217a270f1dd77ed61b8d3c1570c0a4;hp=50da1adec35cd6c2d91c56012da708e0f24d11af;hpb=2503d23b5a113adee89b2631770a8dbfd9ca1351;p=thirdparty%2Fmdadm.git diff --git a/Create.c b/Create.c index 50da1ade..68a42301 100644 --- a/Create.c +++ b/Create.c @@ -71,6 +71,8 @@ int Create(struct supertype *st, char *mddev, int mdfd, int rv; int bitmap_fd; int have_container = 0; + int container_fd; + int need_mdmon = 0; unsigned long long bitmapsize; struct mdinfo *sra; struct mdinfo info; @@ -94,10 +96,10 @@ int Create(struct supertype *st, char *mddev, int mdfd, } } if (level == UnSet) { - /* "ddf" metadata only supports one level - should possibly + /* "ddf" and "imsm" metadata only supports one level - should possibly * push this into metadata handler?? */ - if (st && st->ss == &super_ddf) + if (st && (st->ss == &super_ddf || st->ss == &super_imsm)) level = LEVEL_CONTAINER; } @@ -510,6 +512,8 @@ int Create(struct supertype *st, char *mddev, int mdfd, if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid)) return 1; + st->ss->getinfo_super(st, &info); + if (bitmap_file && vers < 9003) { major_num = BITMAP_MAJOR_HOSTENDIAN; #ifdef __BIG_ENDIAN @@ -537,7 +541,37 @@ int Create(struct supertype *st, char *mddev, int mdfd, if (st->ss->external) { char ver[100]; - strcat(strcpy(ver, "external:"), st->ss->text_version); + strcat(strcpy(ver, "external:"), + info.text_version); + if (st->ss->external == 2) { + /* 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)) { + fprintf(stderr, Name ": mdmon already running " + "for %s - sorry\n", + devnum2devname(st->container_dev)); + return 1; + } + need_mdmon = 1; + } if ((vers % 100) < 2 || sra == NULL || sysfs_set_str(sra, NULL, "metadata_version", @@ -632,15 +666,15 @@ int Create(struct supertype *st, char *mddev, int mdfd, fd, dv->devname); break; case 2: + close(fd); info.component_size = info.array.size * 2; info.errors = 0; rv = 0; if (st->ss->external) { - rv = sysfs_add_disk(sra, fd, &info); - close(fd); + st->ss->getinfo_super_n(st, &info); + rv = sysfs_add_disk(sra, &info); } else { - close(fd); rv = ioctl(mdfd, ADD_NEW_DISK, &info.disk); } @@ -666,15 +700,56 @@ int Create(struct supertype *st, char *mddev, int mdfd, /* No need to start */ ; else if (runstop == 1 || subdevs >= raiddisks) { - mdu_param_t param; - if (ioctl(mdfd, RUN_ARRAY, ¶m)) { - fprintf(stderr, Name ": RUN_ARRAY failed: %s\n", - strerror(errno)); - Manage_runstop(mddev, mdfd, -1, 0); - return 1; + if (st->ss->external) { + switch(level) { + case LEVEL_LINEAR: + case LEVEL_MULTIPATH: + case 0: + sysfs_set_str(sra, NULL, "array_state", + "active"); + need_mdmon = 0; + break; + default: + sysfs_set_str(sra, NULL, "array_state", + "readonly"); + break; + } + } else { + mdu_param_t param; + if (ioctl(mdfd, RUN_ARRAY, ¶m)) { + fprintf(stderr, Name ": RUN_ARRAY failed: %s\n", + strerror(errno)); + Manage_runstop(mddev, mdfd, -1, 0); + return 1; + } } if (verbose >= 0) fprintf(stderr, Name ": array %s started.\n", mddev); + if (st->ss->external == 2) { + 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); + close(container_fd); + } } else { fprintf(stderr, Name ": not starting array - not enough devices.\n"); }