X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Create.c;h=f63afa833cf02592e4593e6b6ce9b97dd2b2f107;hb=85f9b5f798f7fded7145df7b250744e216251ad7;hp=87cfebf9d56818b32ce33cc34e24e47944272e58;hpb=7f91af49ad09adc1b93346f7ad654e25534f35b7;p=thirdparty%2Fmdadm.git diff --git a/Create.c b/Create.c index 87cfebf9..f63afa83 100644 --- a/Create.c +++ b/Create.c @@ -32,6 +32,44 @@ #include "md_p.h" #include +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, @@ -78,7 +116,11 @@ int Create(struct supertype *st, char *mddev, 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; @@ -145,13 +187,11 @@ int Create(struct supertype *st, char *mddev, else st = NULL; } + if (have_container) + subdevs = raiddisks; } if (fd >= 0) close(fd); - if (have_container) { - subdevs = 0; - devlist = NULL; - } } if (st && st->ss->external && sparedisks) { fprintf(stderr, @@ -174,32 +214,12 @@ int Create(struct supertype *st, char *mddev, } /* 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*/ @@ -236,16 +256,23 @@ int Create(struct supertype *st, char *mddev, 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) { @@ -272,9 +299,11 @@ int Create(struct supertype *st, char *mddev, 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; } @@ -289,9 +318,11 @@ int Create(struct supertype *st, char *mddev, 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)) { @@ -311,7 +342,7 @@ int Create(struct supertype *st, char *mddev, } if (size && freesize < size) { - fprintf(stderr, Name ": %s is smaller that given size." + fprintf(stderr, Name ": %s is smaller than given size." " %lluK < %lluK + metadata\n", dname, freesize, size); fail = 1; @@ -339,6 +370,8 @@ int Create(struct supertype *st, char *mddev, close(fd); } } + if (have_container) + info.array.working_disks = raiddisks; if (fail) { fprintf(stderr, Name ": create aborted\n"); return 1; @@ -354,7 +387,7 @@ int Create(struct supertype *st, char *mddev, /* 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; @@ -364,13 +397,21 @@ int Create(struct supertype *st, char *mddev, 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? ")) { @@ -387,7 +428,8 @@ int Create(struct supertype *st, char *mddev, * as missing, so that a reconstruct happens (faster than re-parity) * FIX: Can we do this for raid6 as well? */ - if (assume_clean==0 && force == 0 && first_missing >= raiddisks) { + if (st->ss->external == 0 && + assume_clean==0 && force == 0 && first_missing >= raiddisks) { switch ( level ) { case 4: case 5: @@ -421,9 +463,11 @@ int Create(struct supertype *st, char *mddev, } /* We need to create the device */ - mdfd = create_mddev(mddev, autof); + map_lock(&map); + mdfd = create_mddev(mddev, name, autof, LOCAL, chosen_name); if (mdfd < 0) return 1; + mddev = chosen_name; vers = md_get_version(mdfd); if (vers < 9000) { @@ -439,6 +483,7 @@ int Create(struct supertype *st, char *mddev, goto abort; } } + /* Ok, lets try some ioctls */ info.array.level = level; @@ -514,6 +559,7 @@ int Create(struct supertype *st, char *mddev, * /dev/md/home -> home * /dev/mdhome -> home */ + /* FIXME compare this with rules in create_mddev */ name = strrchr(mddev, '/'); if (name) { name++; @@ -558,6 +604,10 @@ int Create(struct supertype *st, char *mddev, " %s metadata\n", info.text_version); } + map_update(&map, fd2devnum(mdfd), info.text_version, + info.uuid, chosen_name); + map_unlock(&map); + if (bitmap_file && vers < 9003) { major_num = BITMAP_MAJOR_HOSTENDIAN; #ifdef __BIG_ENDIAN @@ -658,10 +708,15 @@ int Create(struct supertype *st, char *mddev, 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: @@ -678,30 +733,43 @@ int Create(struct supertype *st, char *mddev, if (dv->writemostly == 1) inf->disk.state |= (1<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; @@ -719,7 +787,8 @@ int Create(struct supertype *st, char *mddev, } 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); @@ -729,11 +798,13 @@ int Create(struct supertype *st, char *mddev, free(infos); st->ss->free_super(st); - /* param is not actually used */ - if (level == LEVEL_CONTAINER) - /* No need to start */ - ; - else if (runstop == 1 || subdevs >= raiddisks) { + if (level == LEVEL_CONTAINER) { + /* 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); + } else if (runstop == 1 || subdevs >= raiddisks) { if (st->ss->external) { switch(level) { case LEVEL_LINEAR: @@ -750,6 +821,7 @@ int Create(struct supertype *st, char *mddev, } sysfs_set_safemode(&info, safe_mode_delay); } else { + /* param is not actually used */ mdu_param_t param; if (ioctl(mdfd, RUN_ARRAY, ¶m)) { fprintf(stderr, Name ": RUN_ARRAY failed: %s\n", @@ -767,6 +839,7 @@ int Create(struct supertype *st, char *mddev, ping_monitor(devnum2devname(st->container_dev)); close(container_fd); } + wait_for(chosen_name); } else { fprintf(stderr, Name ": not starting array - not enough devices.\n"); }