From 682c705194a869b882cd710d5f996142912db390 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 14 Jun 2001 05:33:53 +0000 Subject: mdctl-v0.3 --- Assemble.c | 48 +++++++------- Create.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- Detail.c | 23 ++++--- Examine.c | 25 +++++--- Makefile | 3 + Manage.c | 160 +++++++++++++++++++++++++++++++++++++++++++++- ReadMe.c | 43 ++++++++++++- TAGS | 140 ++++++++++++++++++++++++++++++++++++++++ TODO | 11 +++- makedist | 6 +- mdctl.c | 114 +++++++++++++++++---------------- mdctl.h | 25 +++++--- util.c | 119 ++++++++++++++++++++++++++++++++-- 13 files changed, 808 insertions(+), 120 deletions(-) create mode 100644 TAGS diff --git a/Assemble.c b/Assemble.c index 504bde7..fdaff09 100644 --- a/Assemble.c +++ b/Assemble.c @@ -107,7 +107,7 @@ int Assemble(char *mddev, int mdfd, int most_recent = 0; if (!mddev && !scan) { - fputs("mdctl: internal error - Assemble called with no devie or scan\n", stderr); + fputs(Name ": internal error - Assemble called with no devie or scan\n", stderr); return 1; } if (!mddev) { @@ -115,7 +115,7 @@ int Assemble(char *mddev, int mdfd, int found = 0; device_list = conf_get_uuids(conffile); if (!device_list) { - fprintf(stderr, "mdctl: No devices found in config file\n"); + fprintf(stderr, Name ": No devices found in config file\n"); return 1; } while (device_list) { @@ -123,7 +123,7 @@ int Assemble(char *mddev, int mdfd, mdfd = open(device_list->devname, O_RDONLY, 0); if (mdfd < 0) { fprintf(stderr, - "mdctl: error opening %s: %s\n", + Name ": error opening %s: %s\n", device_list->devname, strerror(errno)); continue; @@ -140,7 +140,7 @@ int Assemble(char *mddev, int mdfd, } if (found) return 0; - fprintf(stderr,"mdctl: Did not successful Assemble any devices\n"); + fprintf(stderr,Name ": Did not successful Assemble any devices\n"); return 1; } @@ -149,19 +149,19 @@ int Assemble(char *mddev, int mdfd, */ vers = md_get_version(mdfd); if (vers <= 0) { - fprintf(stderr, "mdctl: %s appears not to be an md device.\n"); + fprintf(stderr, Name ": %s appears not to be an md device.\n"); return 1; } - if (vers < (90<<8)) { - fprintf(stderr, "mdctl: Assemble requires driver version 0.90.0 or later.\n" + if (vers < 9000) { + fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n" " Upgrade your kernel or try --Build\n"); return 1; } - if (get_linux_version() < 0x020400) + if (get_linux_version() < 2004000) old_linux = 1; if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) { - fprintf(stderr, "mdctl: device %s already active - cannot assemble it\n", + fprintf(stderr, Name ": device %s already active - cannot assemble it\n", mddev); return 1; } @@ -179,7 +179,7 @@ int Assemble(char *mddev, int mdfd, device_list = device_list->next; if (!device_list) { - fprintf(stderr, "mdctl: --scan set and no uuid found for %s in config file.\n", + fprintf(stderr, Name ": --scan set and no uuid found for %s in config file.\n", mddev); return 1; } @@ -198,7 +198,7 @@ int Assemble(char *mddev, int mdfd, devlist = conf_get_devs(conffile); if (subdevs == 0 && devlist == NULL) { - fprintf(stderr, "mdctl: no devices given for %s\n", mddev); + fprintf(stderr, Name ": no devices given for %s\n", mddev); return 1; } /* now for each device */ @@ -225,26 +225,26 @@ int Assemble(char *mddev, int mdfd, dfd = open(devname, O_RDONLY, 0); if (dfd < 0) { if (inargv || verbose) - fprintf(stderr, "mdctl: cannot open device %s: %s\n", + fprintf(stderr, Name ": cannot open device %s: %s\n", devname, strerror(errno)); continue; } if (fstat(dfd, &stb)< 0) { /* Impossible! */ - fprintf(stderr, "mdctl: fstat failed for %s: %s\n", + fprintf(stderr, Name ": fstat failed for %s: %s\n", devname, strerror(errno)); close(dfd); continue; } if ((stb.st_mode & S_IFMT) != S_IFBLK) { - fprintf(stderr, "mdctl: %d is not a block device.\n", + fprintf(stderr, Name ": %d is not a block device.\n", devname); close(dfd); continue; } if (load_super(dfd, &super)) { if (inargv || verbose) - fprintf( stderr, "mdctl: no RAID superblock on %s\n", + fprintf( stderr, Name ": no RAID superblock on %s\n", devname); close(dfd); continue; @@ -252,7 +252,7 @@ int Assemble(char *mddev, int mdfd, close(dfd); if (compare_super(&first_super, &super)) { if (inargv || verbose) - fprintf(stderr, "mdctl: superblock on %s doesn't match\n", + fprintf(stderr, Name ": superblock on %s doesn't match\n", devname); continue; } @@ -260,7 +260,7 @@ int Assemble(char *mddev, int mdfd, uuid_from_super(this_uuid, &first_super); if (!same_uuid(this_uuid, uuid)) { if (inargv || verbose) - fprintf(stderr, "mdctl: %s has wrong uuid.\n", + fprintf(stderr, Name ": %s has wrong uuid.\n", devname); continue; } @@ -271,7 +271,7 @@ int Assemble(char *mddev, int mdfd, /* Ok, this one is at least worth considering */ if (devcnt >= MD_SB_DISKS) { - fprintf(stderr, "mdctl: ouch - too many devices appear to be in this array. Ignoring %s\n", + fprintf(stderr, Name ": ouch - too many devices appear to be in this array. Ignoring %s\n", devname); continue; } @@ -295,7 +295,7 @@ int Assemble(char *mddev, int mdfd, } if (devcnt == 0) { - fprintf(stderr, "mdctl: no devices found for %s\n", + fprintf(stderr, Name ": no devices found for %s\n", mddev); return 1; } @@ -317,14 +317,14 @@ int Assemble(char *mddev, int mdfd, * not up-to-date, update the superblock * and add it. */ - fprintf(stderr,"NoImplementedYet\n"); + fprintf(stderr,"NotImplementedYet\n"); /* FIXME */ exit(2); } /* Almost ready to actually *do* something */ if (!old_linux) { if (ioctl(mdfd, SET_ARRAY_INFO, NULL) != 0) { - fprintf(stderr, "mdctl: SET_ARRAY_INFO failed for %s: %s\n", + fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n", mddev, strerror(errno)); return 1; } @@ -337,14 +337,14 @@ int Assemble(char *mddev, int mdfd, disk.major = devices[j].major; disk.minor = devices[j].minor; if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) { - fprintf(stderr, "mdctl: failed to add %s to %s: %s\n", + fprintf(stderr, Name ": failed to add %s to %s: %s\n", devices[j].devname, mddev, strerror(errno)); } else okcnt--; } else if (verbose) - fprintf(stderr, "mdctl: no uptodate device for slot %d of %s\n", + fprintf(stderr, Name ": no uptodate device for slot %d of %s\n", i, mddev); } if (runstop == 1 || @@ -352,7 +352,7 @@ int Assemble(char *mddev, int mdfd, enough(first_super.level, first_super.raid_disks, okcnt))) { if (ioctl(mdfd, RUN_ARRAY, NULL)==0) return 0; - fprintf(stderr, "mdctl: failed to RUN_ARRAY %s: %s\n", + fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n", mddev, strerror(errno)); return 1; } diff --git a/Create.c b/Create.c index dda54fd..ac776c2 100644 --- a/Create.c +++ b/Create.c @@ -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=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= 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; } diff --git a/Detail.c b/Detail.c index 9f81e04..3349c3a 100644 --- a/Detail.c +++ b/Detail.c @@ -43,31 +43,32 @@ int Detail(char *dev) mdu_array_info_t array; int d; time_t atime; + char *c; if (fd < 0) { - fprintf(stderr, "mdctl: cannot open %s: %s\n", + fprintf(stderr, Name ": cannot open %s: %s\n", dev, strerror(errno)); return 1; } vers = md_get_version(fd); if (vers < 0) { - fprintf(stderr, "mdctl: %s does not appear to be an md device\n", + fprintf(stderr, Name ": %s does not appear to be an md device\n", dev); close(fd); return 1; } - if (vers < (90<<8)) { - fprintf(stderr, "mdctl: cannot get detail for md device %s: driver version too old.\n", + if (vers < 9000) { + fprintf(stderr, Name ": cannot get detail for md device %s: driver version too old.\n", dev); close(fd); return 1; } if (ioctl(fd, GET_ARRAY_INFO, &array)<0) { if (errno == ENODEV) - fprintf(stderr, "mdctl: md device %s does not appear to be active.\n", + fprintf(stderr, Name ": md device %s does not appear to be active.\n", dev); else - fprintf(stderr, "mdctl: cannot get array detail for %s: %s\n", + fprintf(stderr, Name ": cannot get array detail for %s: %s\n", dev, strerror(errno)); close(fd); return 1; @@ -78,7 +79,8 @@ int Detail(char *dev) array.major_version, array.minor_version, array.patch_version); atime = array.ctime; printf(" Creation Time : %.24s\n", ctime(&atime)); - printf(" Raid Level : %d\n", array.level); + c = map_num(pers, array.level); + printf(" Raid Level : %s\n", c?c:"-unknown-"); printf(" Size : %d\n", array.size); printf(" Raid Disks : %d\n", array.raid_disks); printf(" Total Disks : %d\n", array.nr_disks); @@ -96,7 +98,10 @@ int Detail(char *dev) printf(" Failed Drives : %d\n", array.failed_disks); printf(" Spare Drives : %d\n", array.spare_disks); printf("\n"); - printf(" Layout : %d\n", array.layout); + if (array.level == 5) { + c = map_num(r5layout, array.layout); + printf(" Layout : %s\n", c?c:"-unknown-"); + } printf(" Chunk Size : %dK\n", array.chunk_size/1024); printf("\n"); printf(" Number Major Minor RaidDisk State\n"); @@ -104,7 +109,7 @@ int Detail(char *dev) mdu_disk_info_t disk; disk.number = d; if (ioctl(fd, GET_DISK_INFO, &disk) < 0) { - fprintf(stderr, "mdctl: cannot get disk detail for disk %d: %s\n", + fprintf(stderr, Name ": cannot get disk detail for disk %d: %s\n", d, strerror(errno)); continue; } diff --git a/Examine.c b/Examine.c index ea223c6..f2498ec 100644 --- a/Examine.c +++ b/Examine.c @@ -51,10 +51,11 @@ int Examine(char *dev) time_t atime; mdp_super_t super; int d; + char *c; int rv; if (fd < 0) { - fprintf(stderr,"mdctl: cannot open %s: %s\n", + fprintf(stderr,Name ": cannot open %s: %s\n", dev, strerror(errno)); return 1; } @@ -63,30 +64,30 @@ int Examine(char *dev) close(fd); switch(rv) { case 1: - fprintf(stderr, "mdctl: cannot find device size for %s: %s\n", + fprintf(stderr, Name ": cannot find device size for %s: %s\n", dev, strerror(errno)); return 1; case 2: -/* fprintf(stderr, "mdctl: %s is too small for md: size is %ld sectors\n", +/* fprintf(stderr, Name ": %s is too small for md: size is %ld sectors\n", dev, size); */ - fprintf(stderr, "mdctl: %s is too small for md\n", + fprintf(stderr, Name ": %s is too small for md\n", dev); return 1; case 3: - fprintf(stderr, "mdctl: Cannot seek to superblock on %s: %s\n", + fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n", dev, strerror(errno)); return 1; case 4: - fprintf(stderr, "mdctl: Cannot read superblock on %s\n", + fprintf(stderr, Name ": Cannot read superblock on %s\n", dev); return 1; case 5: - fprintf(stderr, "mdctl: No super block found on %s (Expected magic %08x, got %08x)\n", + fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n", dev, MD_SB_MAGIC, super.md_magic); return 1; case 6: - fprintf(stderr, "mdctl: Cannot interpret superblock on %s - version is %d\n", + fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n", dev, super.major_version); return 1; } @@ -104,7 +105,8 @@ int Examine(char *dev) atime = super.ctime; printf(" Creation Time : %.24s\n", ctime(&atime)); - printf(" Raid Level : %d\n", super.level); + c=map_num(pers, super.level); + printf(" Raid Level : %s\n", c?c:"-unknown-"); printf(" Size : %d\n", super.size); printf(" Raid Disks : %d\n", super.raid_disks); printf(" Total Disks : %d\n", super.nr_disks); @@ -122,7 +124,10 @@ int Examine(char *dev) printf(" - checksum not checked yet - \n"); printf(" Events : %d.%d\n", super.events_hi, super.events_lo); printf("\n"); - printf(" Layout : %d\n", super.layout); + if (super.level == 5) { + c = map_num(r5layout, super.layout); + printf(" Layout : %s\n", c?c:"-unknown-"); + } printf(" Chunk Size : %dK\n", super.chunk_size/1024); printf("\n"); printf(" Number Major Minor RaidDisk State\n"); diff --git a/Makefile b/Makefile index 4fe9ba8..0168923 100644 --- a/Makefile +++ b/Makefile @@ -42,3 +42,6 @@ clean : dist : clean ./makedist + +TAGS : + etags *.h *.c diff --git a/Manage.c b/Manage.c index 302a425..7357339 100644 --- a/Manage.c +++ b/Manage.c @@ -28,16 +28,174 @@ */ #include "mdctl.h" +#include "md_u.h" +#include "md_p.h" int Manage_ro(char *devname, int fd, int readonly) { + /* switch to readonly or rw + * + * requires >= 0.90.0 + * first check that array is runing + * use RESTART_ARRAY_RW or STOP_ARRAY_RO + * + */ + mdu_array_info_t array; + + if (md_get_version(fd) < 9000) { + fprintf(stderr, Name ": need md driver version 0.90.0 or later\n"); + return 1; + } + if (ioctl(fd, GET_ARRAY_INFO, &array)) { + fprintf(stderr, Name ": %s does not appear to be active.\n", + devname); + return 1; + } + + if (readonly>0) { + if (ioctl(fd, STOP_ARRAY_RO, NULL)) { + fprintf(stderr, Name ": failed to set readonly for %s: %s\n", + devname, strerror(errno)); + return 1; + } + } else if (readonly < 0) { + if (ioctl(fd, RESTART_ARRAY_RW, NULL)) { + fprintf(stderr, Name ": fail to re writable for %s: %s\n", + devname, strerror(errno)); + return 1; + } + } + return 0; } int Manage_runstop(char *devname, int fd, int runstop) { + /* Run or stop the array. array must already be configured + * required >= 0.90.0 + */ + mdu_array_info_t array; + mdu_param_t param; /* unused */ + + if (md_get_version(fd) < 9000) { + fprintf(stderr, Name ": need md driver version 0.90.0 or later\n"); + return 1; + } + if (ioctl(fd, GET_ARRAY_INFO, &array)) { + fprintf(stderr, Name ": %s does not appear to be active.\n", + devname); + return 1; + } + + if (runstop>0) { + if (ioctl(fd, RUN_ARRAY, ¶m)) { + fprintf(stderr, Name ": failed to run array %s: %s\n", + devname, strerror(errno)); + return 1; + } + } else if (runstop < 0){ + if (ioctl(fd, STOP_ARRAY, NULL)) { + fprintf(stderr, Name ": fail to re writable for %s: %s\n", + devname, strerror(errno)); + return 1; + } + } + return 0; } int Manage_subdevs(char *devname, int fd, int devcnt, char *devnames[], int devmodes[]) -{ + { + /* do something to each dev. + * devmode can be + * 'a' - add the device + * try HOT_ADD_DISK + * If that fails EINVAL, try ADD_NEW_DISK + * 'r' - remove the device HOT_REMOVE_DISK + * 'f' - set the device faulty SET_DISK_FAULTY + */ + mdu_array_info_t array; + mdu_disk_info_t disc; + struct stat stb; + int i,j; + + if (ioctl(fd, GET_ARRAY_INFO, &array)) { + fprintf(stderr, Name ": cannot get array info for %s\n", + devname); + return 1; + } + for (i=0 ; i $target/$base chmod a+r $target/$base -ls -l $target/$base \ No newline at end of file +ls -l $target/$base diff --git a/mdctl.c b/mdctl.c index a2ece91..5a16646 100644 --- a/mdctl.c +++ b/mdctl.c @@ -40,6 +40,7 @@ int main(int argc, char *argv[]) int i; int chunk = 0; + int size = 0; int level = -10; int layout = -1; int raiddisks = 0; @@ -73,7 +74,7 @@ int main(int argc, char *argv[]) case 'E': /* setting mode - only once */ if (mode) { - fprintf(stderr, "mdctl: --%s/-%c not allowed, mode already set to %s\n", + fprintf(stderr, Name ": --%s/-%c not allowed, mode already set to %s\n", long_options[opt-'A'+1].name, long_options[opt-'A'+1].val, long_options[mode-'A'+1].name); @@ -107,7 +108,7 @@ int main(int argc, char *argv[]) mddev = optarg; else { if (subdevs +1 >= MD_SB_DISKS) { - fprintf(stderr, "mdctl: too many devices at %s - current limit -s %d\n", + fprintf(stderr, Name ": too many devices at %s - current limit -s %d\n", optarg, MD_SB_DISKS); exit(2); } @@ -133,46 +134,52 @@ int main(int argc, char *argv[]) case O('C','c'): case O('B','c'): /* chunk or rounding */ if (chunk) { - fprintf(stderr, "mdctl: chunk/rounding may only be specified once. " + fprintf(stderr, Name ": chunk/rounding may only be specified once. " "Second value is %s.\n", optarg); exit(2); } chunk = strtol(optarg, &c, 10); - if (!optarg[0] || *c) { - fprintf(stderr, "mdctl: invalid chunk/rounding value: %s\n", + if (!optarg[0] || *c || chunk<4 || ((chunk-1)&chunk)) { + fprintf(stderr, Name ": invalid chunk/rounding value: %s\n", optarg); exit(2); } continue; + case O('c','z'): /* size */ + if (size) { + fprintf(stderr, Name ": size may only be specified once. " + "Second value is %s.\n", optarg); + exit(2); + } + size = strtol(optarg, &c, 10); + if (!optarg[0] || *c || size < 4) { + fprintf(stderr, Name ": invalid size: %s\n", + optarg); + exit(2); + } + continue; + case O('C','l'): case O('B','l'): /* set raid level*/ if (level != -10) { - fprintf(stderr, "mdctl: raid level may only be set once. " + fprintf(stderr, Name ": raid level may only be set once. " "Second value is %s.\n", optarg); exit(2); } - if (strcmp(optarg,"linear")==0) - level = -1; - else if (strlen(optarg)==1 && strchr("01245", optarg[0])) - level = optarg[0]-'0'; - else { - fprintf(stderr, "mdctl: invalid raid level: %s\n", + level = map_name(pers, optarg); + if (level == -10) { + fprintf(stderr, Name ": invalid raid level: %s\n", optarg); exit(2); } if (level > 0 && mode == 'B') { - fprintf(stderr, "mdctl: Raid level %s not permitted with --build.\n", - optarg); - exit(2); - } - if (layout >=0 && level < 4) { - fprintf(stderr, "mdctl: raid level %s is incompatible with layout setting\n", + fprintf(stderr, Name ": Raid level %s not permitted with --build.\n", optarg); exit(2); } if (sparedisks > 0 && level < 1) { - fprintf(stderr, "mdctl: raid level %s is incompatible with spare-disks setting.\n", + fprintf(stderr, Name ": raid level %s is incompatible with spare-disks setting.\n", optarg); exit(2); } @@ -180,39 +187,40 @@ int main(int argc, char *argv[]) case O('C','p'): /* raid5 layout */ if (layout >= 0) { - fprintf(stderr,"mdctl: layout may only be sent once. " + fprintf(stderr,Name ": layout may only be sent once. " "Second value was %s\n", optarg); exit(2); } - if (level > -10 && level < 4) { - fprintf(stderr,"mdctl: layout is incompatible with raid levels below 4.\n"); - exit(2); - } - if (strcmp(optarg, "left-symmetric")==0 || strcmp(optarg,"ls")==0) - layout = ALGORITHM_LEFT_SYMMETRIC; - else if (strcmp(optarg, "left-asymmetric")==0 || strcmp(optarg,"la")==0) - layout = ALGORITHM_LEFT_ASYMMETRIC; - else if (strcmp(optarg, "right-symmetric")==0 || strcmp(optarg,"rs")==0) - layout = ALGORITHM_RIGHT_SYMMETRIC; - else if (strcmp(optarg, "right-asymmetric")==0 || strcmp(optarg,"ra")==0) - layout = ALGORITHM_RIGHT_ASYMMETRIC; - else { - fprintf(stderr,"mdctl: %s is not a valid layout value\n", - optarg); - exit(2); + switch(level) { + default: + fprintf(stderr, Name ": layout now meaningful for %s arrays.\n", + map_num(pers, level)); + exit(2); + case -10: + fprintf(stderr, Name ": raid level must be given before layout.\n"); + exit(2); + + case 5: + layout = map_name(r5layout, optarg); + if (layout==-10) { + fprintf(stderr, Name ": layout %s not understood for raid5.\n", + optarg); + exit(2); + } + break; } continue; case O('C','n'): case O('B','n'): /* number of raid disks */ if (raiddisks) { - fprintf(stderr, "mdctl: raid-disks set twice: %d and %s\n", + fprintf(stderr, Name ": raid-disks set twice: %d and %s\n", raiddisks, optarg); exit(2); } raiddisks = strtol(optarg, &c, 10); if (!optarg[0] || *c || raiddisks<=0 || raiddisks > MD_SB_DISKS) { - fprintf(stderr, "mdctl: invalid number of raid disks: %s\n", + fprintf(stderr, Name ": invalid number of raid disks: %s\n", optarg); exit(2); } @@ -220,18 +228,18 @@ int main(int argc, char *argv[]) case O('C','x'): /* number of spare (eXtra) discs */ if (sparedisks) { - fprintf(stderr,"mdctl: spare-disks set twice: %d and %s\n", + fprintf(stderr,Name ": spare-disks set twice: %d and %s\n", sparedisks, optarg); exit(2); } if (level > -10 && level < 1) { - fprintf(stderr, "mdctl: spare-disks setting is incompatible with raid level %d\n", + fprintf(stderr, Name ": spare-disks setting is incompatible with raid level %d\n", level); exit(2); } sparedisks = strtol(optarg, &c, 10); if (!optarg[0] || *c || sparedisks < 0 || sparedisks > MD_SB_DISKS - raiddisks) { - fprintf(stderr, "mdctl: invalid number of spare disks: %s\n", + fprintf(stderr, Name ": invalid number of spare disks: %s\n", optarg); exit(2); } @@ -243,21 +251,21 @@ int main(int argc, char *argv[]) continue; case O('A','u'): /* uuid of array */ if (uuidset) { - fprintf(stderr, "mdctl: uuid cannot bet set twice. " + fprintf(stderr, Name ": uuid cannot bet set twice. " "Second value %s.\n", optarg); exit(2); } if (parse_uuid(optarg, uuid)) uuidset = 1; else { - fprintf(stderr,"mdctl: Bad uuid: %s\n", optarg); + fprintf(stderr,Name ": Bad uuid: %s\n", optarg); exit(2); } continue; case O('A','c'): /* config file */ if (configfile) { - fprintf(stderr, "mdctl: configfile cannot be set twice. " + fprintf(stderr, Name ": configfile cannot be set twice. " "Second value is %s.\n", optarg); exit(2); } @@ -289,14 +297,14 @@ int main(int argc, char *argv[]) case O('B','R'): case O('C','R'): /* Run the array */ if (runstop < 0) { - fprintf(stderr, "mdctl: Cannot both Stop and Run an array\n"); + fprintf(stderr, Name ": Cannot both Stop and Run an array\n"); exit(2); } runstop = 1; continue; case O('@','S'): if (runstop > 0) { - fprintf(stderr, "mdctl: Cannot both Run and Stop an array\n"); + fprintf(stderr, Name ": Cannot both Run and Stop an array\n"); exit(2); } runstop = -1; @@ -304,7 +312,7 @@ int main(int argc, char *argv[]) case O('@','o'): if (readonly < 0) { - fprintf(stderr, "mdctl: Cannot have both readonly and readwrite\n"); + fprintf(stderr, Name ": Cannot have both readonly and readwrite\n"); exit(2); } readonly = 1; @@ -320,7 +328,7 @@ int main(int argc, char *argv[]) /* We have now processed all the valid options. Anything else is * an error */ - fprintf(stderr, "mdctl: option %c not valid in mode %c\n", + fprintf(stderr, Name ": option %c not valid in mode %c\n", opt, mode); exit(2); @@ -341,17 +349,17 @@ int main(int argc, char *argv[]) */ if (mode !='D' && mode !='E' && ! (mode =='A' && scan)) { if (!mddev) { - fprintf(stderr, "mdctl: an md device must be given in this mode\n"); + fprintf(stderr, Name ": an md device must be given in this mode\n"); exit(2); } mdfd = open(mddev, O_RDWR, 0); if (mdfd < 0) { - fprintf(stderr,"mdctl: error opening %s: %s\n", + fprintf(stderr,Name ": error opening %s: %s\n", mddev, strerror(errno)); exit(1); } if (md_get_version(mdfd) <= 0) { - fprintf(stderr, "mdctl: %s does not appear to be an md device\n", + fprintf(stderr, Name ": %s does not appear to be an md device\n", mddev); close(mdfd); exit(1); @@ -378,8 +386,8 @@ int main(int argc, char *argv[]) rv = Build(mddev, mdfd, chunk, level, raiddisks, subdevs,subdev); break; case 'C': /* Create */ - rv = Create(mddev, mdfd, chunk, level, layout, raiddisks, sparedisks, - subdevs,subdev,runstop); + rv = Create(mddev, mdfd, chunk, level, layout, size, raiddisks, sparedisks, + subdevs,subdev,runstop, verbose); break; case 'D': /* Detail */ for (i=0; imd_magic != MD_SB_MAGIC) @@ -222,3 +222,114 @@ int load_super(int fd, mdp_super_t *super) return 0; } + +int check_ext2(int fd, char *name) +{ + /* + * Check for an ext2fs file system. + * Superblock is always 1K at 1K offset + * + * s_magic is le16 at 56 == 0xEF53 + * report mtime - le32 at 44 + * blocks - le32 at 4 + * logblksize - le32 at 24 + */ + unsigned char sb[1024]; + time_t mtime; + int size, bsize; + if (lseek(fd, 1024,0)!= 1024) + return 0; + if (read(fd, sb, 1024)!= 1024) + return 0; + if (sb[56] != 0x53 || sb[57] != 0xef) + return 0; + + mtime = sb[44]|(sb[45]|(sb[46]|sb[47]<<8)<<8)<<8; + bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8; + size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8; + fprintf(stderr, Name ": %s appears to contain an ext2fs file system\n", + name); + fprintf(stderr," size=%dK mtime=%s", + size*(1<name) { + if (map->num == num) + return map->name; + map++; + } + return NULL; +} + +int map_name(mapping_t *map, char *name) +{ + while (map->name) { + if (strcmp(map->name, name)==0) + return map->num; + map++; + } + return -10; +} -- cgit