diff options
author | Neil Brown <neilb@suse.de> | 2001-06-14 05:33:53 +0000 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2001-06-14 05:33:53 +0000 |
commit | 682c705194a869b882cd710d5f996142912db390 (patch) | |
tree | f9da32bd70e47d558a84530e34c2b8feb17dbfa0 /Create.c | |
parent | 64c4757e27fe7d688685e9a86ff87a3331a88979 (diff) | |
download | mdadm-682c705194a869b882cd710d5f996142912db390.tar.gz mdadm-682c705194a869b882cd710d5f996142912db390.tar.xz mdadm-682c705194a869b882cd710d5f996142912db390.zip |
mdctl-v0.3mdctl-v0.3
Diffstat (limited to 'Create.c')
-rw-r--r-- | Create.c | 211 |
1 files changed, 209 insertions, 2 deletions
@@ -28,10 +28,217 @@ */ #include "mdctl.h" +#include "md_u.h" +#include "md_p.h" int Create(char *mddev, int mdfd, - int chunk, int level, int layout, int raiddisks, int sparedisks, + int chunk, int level, int layout, int size, int raiddisks, int sparedisks, int subdevs, char *subdev[], - int runstop) + int runstop, int verbose) { + /* + * Create a new raid array. + * + * First check that necessary details are available + * (i.e. level, raid-disks) + * + * Then check each disk to see what might be on it + * and report anything interesting. + * + * If anything looks odd, and runstop not set, + * abort. + * + * SET_ARRAY_INFO and ADD_NEW_DISK, and + * if runstop==run, or raiddisks diskswere used, + * RUN_ARRAY + */ + int minsize, maxsize; + int maxdisc= -1, mindisc = -1; + int i; + int fail=0, warn=0; + + mdu_array_info_t array; + mdu_param_t param; + + + if (md_get_version(mdfd) < 9000) { + fprintf(stderr, Name ": Create requires md driver verison 0.90.0 or later\n"); + return 1; + } + if (level == -10) { + fprintf(stderr, + Name ": a RAID level is needed to create an array.\n"); + return 1; + } + if (raiddisks < 1) { + fprintf(stderr, + Name ": a number of --raid-disks must be given to create an array\n"); + return 1; + } + if (raiddisks+sparedisks > MD_SB_DISKS) { + fprintf(stderr, + Name ": too many discs requested: %d+%d > %d\n", + raiddisks, sparedisks, MD_SB_DISKS); + return 1; + } + if (subdevs > raiddisks+sparedisks) { + fprintf(stderr, Name ": You have listed more disks (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks); + return 1; + } + /* now set some defaults */ + if (layout == -1) + switch(level) { + default: /* no layout */ + layout = 0; + break; + case 5: + layout = map_name(r5layout, "default"); + if (verbose) + fprintf(stderr, + Name ": layout defaults to %s\n", map_num(r5layout, layout)); + break; + } + + if (chunk == 0) { + chunk = 64; + if (verbose) + fprintf(stderr, Name ": chunk size defaults to 64K\n"); + } + + /* now look at the subdevs */ + for (i=0; i<subdevs; i++) { + char *dname = subdev[i]; + int dsize, freesize; + int fd = open(dname, O_RDONLY, 0); + if (fd <0 ) { + fprintf(stderr, Name ": Cannot open %s: %s\n", + dname, strerror(errno)); + fail=1; + continue; + } + if (ioctl(fd, BLKGETSIZE, &dsize)) { + fprintf(stderr, Name ": Cannot get size of %s: %s\n", + dname, strerror(errno)); + fail = 1; + close(fd); + continue; + } + if (dsize < MD_RESERVED_SECTORS*2) { + fprintf(stderr, Name ": %s is too small: %dK\n", + dname, dsize/2); + fail = 1; + close(fd); + continue; + } + freesize = MD_NEW_SIZE_SECTORS(dsize); + freesize /= 2; + + if (size && freesize < size) { + fprintf(stderr, Name ": %s is smaller that given size." + " %dK < %dK + superblock\n", dname, freesize, size); + fail = 1; + close(fd); + continue; + } + if (maxdisc< 0 || (maxdisc>=0 && freesize > maxsize)) { + maxdisc = i; + maxsize = freesize; + } + if (mindisc < 0 || (mindisc >=0 && freesize < minsize)) { + mindisc = i; + minsize = freesize; + } + warn |= check_ext2(fd, dname); + warn |= check_reiser(fd, dname); + warn |= check_raid(fd, dname); + close(fd); + } + if (fail) { + fprintf(stderr, Name ": create aborted\n"); + return 1; + } + if (size == 0) { + if (mindisc == -1) { + fprintf(stderr, Name ": no size and no drives given - aborting create.\n"); + return 1; + } + size = minsize; + if (verbose) + fprintf(stderr, Name ": size set to %dK\n", size); + } + if ((maxsize-size)*100 > maxsize) { + fprintf(stderr, Name ": largest drive (%s) exceed size (%dK) by more than 1%\n", + subdev[maxdisc], size); + warn = 1; + } + + if (warn) { + if (runstop!= 1) { + if (!ask("Continue creating array? ")) { + fprintf(stderr, Name ": create aborted.\n"); + return 1; + } + } else { + if (verbose) + fprintf(stderr, Name ": creation continuing despite oddities due to --run\n"); + } + } + + /* Ok, lets try some ioctls */ + + array.level = level; + array.size = size; + array.nr_disks = raiddisks+sparedisks; + array.raid_disks = raiddisks; + array.md_minor = 0; + array.not_persistent = 0; + array.state = 0; /* not clean, but no errors */ + array.active_disks=0; + array.working_disks=0; + array.spare_disks=0; + array.failed_disks=0; + array.layout = layout; + array.chunk_size = chunk*1024; + + if (ioctl(mdfd, SET_ARRAY_INFO, &array)) { + fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n", + mddev, strerror(errno)); + return 1; + } + + for (i=0; i<subdevs; i++) { + int fd = open(subdev[i], O_RDONLY, 0); + struct stat stb; + mdu_disk_info_t disk; + if (fd < 0) { + fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n", + subdev[i]); + return 1; + } + fstat(fd, &stb); + disk.number = i; + disk.raid_disk = i; + disk.state = 6; /* active and in sync */ + disk.major = MAJOR(stb.st_rdev); + disk.minor = MINOR(stb.st_rdev); + close(fd); + if (ioctl(mdfd, ADD_NEW_DISK, &disk)) { + fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\b", + subdev[i], strerror(errno)); + return 1; + } + } + + /* param is not actually used */ + if (runstop == 1 || subdevs >= raiddisks) { + if (ioctl(mdfd, RUN_ARRAY, ¶m)) { + fprintf(stderr, Name ": RUN_ARRAY failed: %s\n", + strerror(errno)); + return 1; + } + fprintf(stderr, Name ": array %s started.\n", mddev); + } else { + fprintf(stderr, Name ": not starting array - not enough discs.\n"); + } + return 0; } |