#include "md_p.h"
#include <ctype.h>
+static int default_layout(struct supertype *st, int level, int verbose)
+{
+ int layout = UnSet;
+
+ if (st && st->ss->default_layout)
+ layout = st->ss->default_layout(level);
+
+ if (layout == UnSet)
+ switch(level) {
+ default: /* no layout */
+ layout = 0;
+ break;
+ case 10:
+ layout = 0x102; /* near=2, far=1 */
+ if (verbose > 0)
+ fprintf(stderr,
+ Name ": layout defaults to n1\n");
+ break;
+ case 5:
+ case 6:
+ layout = map_name(r5layout, "default");
+ if (verbose > 0)
+ fprintf(stderr,
+ Name ": layout defaults to %s\n", map_num(r5layout, layout));
+ break;
+ case LEVEL_FAULTY:
+ layout = map_name(faultylayout, "default");
+
+ if (verbose > 0)
+ fprintf(stderr,
+ Name ": layout defaults to %s\n", map_num(faultylayout, layout));
+ break;
+ }
+
+ return layout;
+}
+
+
int Create(struct supertype *st, char *mddev,
int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
char *name, char *homehost, int *uuid,
unsigned long long bitmapsize;
struct mdinfo info, *infos;
int did_default = 0;
+ int do_default_layout = 0;
unsigned long safe_mode_delay = 0;
char chosen_name[1024];
struct map_ent *map = NULL;
+ unsigned long long newsize;
int major_num = BITMAP_MAJOR_HI;
else
st = NULL;
}
+ if (have_container) {
+ subdevs = raiddisks;
+ first_missing = subdevs * 2;
+ second_missing = subdevs * 2;
+ insert_point = subdevs * 2;
+ }
}
if (fd >= 0)
close(fd);
- if (have_container) {
- subdevs = 0;
- devlist = NULL;
- }
}
if (st && st->ss->external && sparedisks) {
fprintf(stderr,
}
/* now set some defaults */
- if (layout == UnSet)
- switch(level) {
- default: /* no layout */
- layout = 0;
- break;
- case 10:
- layout = 0x102; /* near=2, far=1 */
- if (verbose > 0)
- fprintf(stderr,
- Name ": layout defaults to n1\n");
- break;
- case 5:
- case 6:
- layout = map_name(r5layout, "default");
- if (verbose > 0)
- fprintf(stderr,
- Name ": layout defaults to %s\n", map_num(r5layout, layout));
- break;
- case LEVEL_FAULTY:
- layout = map_name(faultylayout, "default");
- if (verbose > 0)
- fprintf(stderr,
- Name ": layout defaults to %s\n", map_num(faultylayout, layout));
- break;
- }
+
+ if (layout == UnSet) {
+ do_default_layout = 1;
+ layout = default_layout(st, level, verbose);
+ }
if (level == 10)
/* check layout fits in array*/
fprintf(stderr, Name ": unknown level %d\n", level);
return 1;
}
-
+
+ newsize = size * 2;
if (st && ! st->ss->validate_geometry(st, level, layout, raiddisks,
- chunk, size, NULL, NULL, verbose>=0))
+ chunk, size*2, NULL, &newsize, verbose>=0))
return 1;
+ if (size == 0) {
+ size = newsize / 2;
+ if (size && verbose > 0)
+ fprintf(stderr, Name ": setting size to %lluK\n",
+ (unsigned long long)size);
+ }
/* now look at the subdevs */
info.array.active_disks = 0;
info.array.working_disks = 0;
dnum = 0;
- for (dv=devlist; dv; dv=dv->next, dnum++) {
+ for (dv=devlist; dv && !have_container; dv=dv->next, dnum++) {
char *dname = dv->devname;
unsigned long long freesize;
if (strcasecmp(dname, "missing")==0) {
char *name = "default";
for(i=0; !st && superlist[i]; i++) {
st = superlist[i]->match_metadata_desc(name);
+ if (do_default_layout)
+ layout = default_layout(st, level, verbose);
if (st && !st->ss->validate_geometry
(st, level, layout, raiddisks,
- chunk, size, dname, &freesize,
+ chunk, size*2, dname, &freesize,
verbose > 0))
st = NULL;
}
st->minor_version != 90)
did_default = 1;
} else {
+ if (do_default_layout)
+ layout = default_layout(st, level, verbose);
if (!st->ss->validate_geometry(st, level, layout,
raiddisks,
- chunk, size, dname,
+ chunk, size*2, dname,
&freesize,
verbose > 0)) {
close(fd);
}
}
+ if (have_container)
+ info.array.working_disks = raiddisks;
if (fail) {
fprintf(stderr, Name ": create aborted\n");
return 1;
/* size is meaningful */
if (!st->ss->validate_geometry(st, level, layout,
raiddisks,
- chunk, minsize,
+ chunk, minsize*2,
NULL, NULL, 0)) {
fprintf(stderr, Name ": devices too large for RAID level %d\n", level);
return 1;
fprintf(stderr, Name ": size set to %lluK\n", size);
}
}
- if (level > 0 && ((maxsize-size)*100 > maxsize)) {
+ if (!have_container && level > 0 && ((maxsize-size)*100 > maxsize)) {
if (runstop != 1 || verbose >= 0)
- fprintf(stderr, Name ": largest drive (%s) exceed size (%lluK) by more than 1%%\n",
+ fprintf(stderr, Name ": largest drive (%s) exceeds size (%lluK) by more than 1%%\n",
maxdisc, size);
warn = 1;
}
+ if (st->ss->detail_platform && st->ss->detail_platform(0, 1) != 0) {
+ if (runstop != 1 || verbose >= 0)
+ fprintf(stderr, Name ": %s unable to enumerate platform support\n"
+ " array may not be compatible with hardware/firmware\n",
+ st->ss->name);
+ warn = 1;
+ }
+
if (warn) {
if (runstop!= 1) {
if (!ask("Continue creating array? ")) {
abort();
if (dnum == insert_point) {
moved_disk = dv;
+ continue;
}
- if (dnum == insert_point ||
- strcasecmp(dv->devname, "missing")==0)
+ if (strcasecmp(dv->devname, "missing")==0)
continue;
+ if (have_container)
+ moved_disk = NULL;
+ if (have_container && dnum < info.array.raid_disks - 1)
+ /* repeatedly use the container */
+ moved_disk = dv;
switch(pass) {
case 1:
if (dv->writemostly == 1)
inf->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
- if (st->ss->external && st->subarray[0])
- fd = open(dv->devname, O_RDWR);
- else
- fd = open(dv->devname, O_RDWR|O_EXCL);
-
- if (fd < 0) {
- fprintf(stderr, Name ": failed to open %s "
- "after earlier success - aborting\n",
- dv->devname);
- goto abort;
+ if (have_container)
+ fd = -1;
+ else {
+ if (st->ss->external && st->subarray[0])
+ fd = open(dv->devname, O_RDWR);
+ else
+ fd = open(dv->devname, O_RDWR|O_EXCL);
+
+ if (fd < 0) {
+ fprintf(stderr, Name ": failed to open %s "
+ "after earlier success - aborting\n",
+ dv->devname);
+ goto abort;
+ }
+ fstat(fd, &stb);
+ inf->disk.major = major(stb.st_rdev);
+ inf->disk.minor = minor(stb.st_rdev);
}
- fstat(fd, &stb);
- inf->disk.major = major(stb.st_rdev);
- inf->disk.minor = minor(stb.st_rdev);
-
- remove_partitions(fd);
- st->ss->add_to_super(st, &inf->disk,
- fd, dv->devname);
+ if (fd >= 0)
+ remove_partitions(fd);
+ if (st->ss->add_to_super(st, &inf->disk,
+ fd, dv->devname))
+ goto abort;
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->disk.minor = minor(stb.st_rdev);
+ if (have_container && verbose > 0)
+ fprintf(stderr, Name ": Using %s for device %d\n",
+ map_dev(inf->disk.major,
+ inf->disk.minor,
+ 0), dnum);
+
+ if (!have_container) {
+ /* getinfo_super might have lost these ... */
+ inf->disk.major = major(stb.st_rdev);
+ inf->disk.minor = minor(stb.st_rdev);
+ }
break;
case 2:
inf->errors = 0;
}
break;
}
- if (dv == moved_disk && dnum != insert_point) break;
+ if (!have_container &&
+ dv == moved_disk && dnum != insert_point) break;
}
if (pass == 1) {
st->ss->write_init_super(st);
/* No need to start. But we should signal udev to
* create links */
sysfs_uevent(&info, "change");
- ;
+ if (verbose >= 0)
+ fprintf(stderr, Name ": container %s prepared.\n", mddev);
+ wait_for(chosen_name);
} else if (runstop == 1 || subdevs >= raiddisks) {
if (st->ss->external) {
switch(level) {