diff options
author | Neil Brown <neilb@suse.de> | 2001-06-14 07:33:53 +0200 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2001-06-14 07:33:53 +0200 |
commit | 682c705194a869b882cd710d5f996142912db390 (patch) | |
tree | f9da32bd70e47d558a84530e34c2b8feb17dbfa0 | |
parent | mdctl-v0.2 (diff) | |
download | mdadm-682c705194a869b882cd710d5f996142912db390.tar.xz mdadm-682c705194a869b882cd710d5f996142912db390.zip |
mdctl-v0.3mdctl-v0.3
-rw-r--r-- | Assemble.c | 48 | ||||
-rw-r--r-- | Create.c | 211 | ||||
-rw-r--r-- | Detail.c | 23 | ||||
-rw-r--r-- | Examine.c | 25 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | Manage.c | 160 | ||||
-rw-r--r-- | ReadMe.c | 43 | ||||
-rw-r--r-- | TAGS | 140 | ||||
-rw-r--r-- | TODO | 11 | ||||
-rwxr-xr-x | makedist | 6 | ||||
-rw-r--r-- | mdctl.c | 114 | ||||
-rw-r--r-- | mdctl.h | 25 | ||||
-rw-r--r-- | util.c | 119 |
13 files changed, 808 insertions, 120 deletions
@@ -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; } @@ -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; } @@ -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; } @@ -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"); @@ -42,3 +42,6 @@ clean : dist : clean ./makedist + +TAGS : + etags *.h *.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<devcnt; i++) { + if (stat(devnames[i], &stb)) { + fprintf(stderr, Name ": cannot find %s: %s\n", + devnames[i], strerror(errno)); + return 1; + } + if ((stb.st_mode & S_IFMT) != S_IFBLK) { + fprintf(stderr, Name ": %s is not a block device.\n", + devnames[i]); + return 1; + } + switch(devmodes[i]){ + default: + fprintf(stderr, Name ": internal error - devmode[%d]=%d\n", + i, devmodes[i]); + return 1; + case 'a': + /* add the device - hot or cold */ + if (ioctl(fd, HOT_ADD_DISK, stb.st_rdev)==0) { + fprintf(stderr, Name ": hot added %s\n", + devnames[i]); + continue; + } + /* try ADD_NEW_DISK. + * we might be creating, we might be assembling, + * it is hard to tell. + * set up number/raid_disk/state just + * in case + */ + for (j=0; j<array.nr_disks; j++) { + if (ioctl(fd, GET_DISK_INFO, &disc)) + break; + if (disc.major==0 && disc.minor==0) + break; + if (disc.state & 8) /* removed */ + break; + } + disc.number =j; + disc.raid_disk = j; + disc.state = 0; + disc.major = MAJOR(stb.st_rdev); + disc.minor = MINOR(stb.st_rdev); + if (ioctl(fd,ADD_NEW_DISK, &disc)) { + fprintf(stderr, Name ": add new disk failed for %s: %s\n", + devnames[i], strerror(errno)); + return 1; + } + fprintf(stderr, Name ": added %s\n", devnames[i]); + break; + + case 'r': + /* hot remove */ + /* FIXME check that is is a current member */ + if (ioctl(fd, HOT_REMOVE_DISK, stb.st_rdev)) { + fprintf(stderr, Name ": hot remove failed for %s: %s\n", + devnames[i], strerror(errno)); + return 1; + } + fprintf(stderr, Name ": hot removed %s\n", devnames[i]); + break; + + case 'f': /* set faulty */ + /* FIXME check current member */ + if (ioctl(fd, SET_DISK_FAULTY, stb.st_rdev)) { + fprintf(stderr, Name ": set disk faulty failed for %s: %s\n", + devnames[i], strerror(errno)); + return 1; + } + fprintf(stderr, Name ": set %s faulty in %s\n", + devnames[i], devname); + break; + } + } + return 0; + } @@ -29,7 +29,7 @@ #include "mdctl.h" -char Version[] = "mdctl - v0.2 - 06 June 2001\n"; +char Version[] = Name " - v0.3 - 14 June 2001\n"; /* * File: ReadMe.c * @@ -78,7 +78,7 @@ char Version[] = "mdctl - v0.2 - 06 June 2001\n"; * command, subsequent Manage commands can finish the job. */ -char short_options[]="-ABCDEhVvc:l:p:n:x:u:c:sarfRSow"; +char short_options[]="-ABCDEhVvc:l:p:n:x:u:c:z:sarfRSow"; struct option long_options[] = { {"manage", 0, 0, '@'}, {"assemble", 0, 0, 'A'}, @@ -99,6 +99,7 @@ struct option long_options[] = { {"layout", 1, 0, 'p'}, {"raid-disks",1, 0, 'n'}, {"spare-disks",1,0, 'x'}, + {"size" ,1, 0, 'z'}, /* For assemble */ {"uuid", 1, 0, 'u'}, @@ -157,6 +158,7 @@ char Help[] = " --layout= : same as --parity\n" " --raid-disks= -n : number of active devices in array\n" " --spare-disks= -x : number of spares (eXtras) to allow space for\n" +" --size= -z : Size (in K) of each drive in RAID1/4/5 - optional\n" "\n" " For assemble:\n" " --uuid= -u : uuid of array to assemble. Devices which don't\n" @@ -192,6 +194,11 @@ char Help_create[] = " be run, though the presence of a '--run' can override this\n" " caution.\n" "\n" +" If the --size option is given, it is not necessary to list any subdevices\n" +" in this command. They can be added later, before a --run.\n" +" If no --size is given, the apparent size of the smallest drive given\n" +" is used.\n" +"\n" " The General management options that are valid with --create are:\n" " --run : insist of running the array even if not all devices\n" " are present or some look odd.\n" @@ -244,3 +251,35 @@ char Help_assemble[] = " not yet documented\n" "\n" ; + + +/* name/number mappings */ + +mapping_t r5layout[] = { + { "left_asymmetric", 0}, + { "right_asymmetric", 1}, + { "left_symmetric", 2}, + { "right_symmetric", 3}, + + { "default", 2}, + { "la", 0}, + { "ra", 1}, + { "ls", 2}, + { "rs", 3}, + { NULL, 0} +}; + +mapping_t pers[] = { + { "linear", -1}, + { "raid0", 0}, + { "0", 0}, + { "stripe", 0}, + { "raid1", 1}, + { "1", 1}, + { "mirror", 1}, + { "raid4", 4}, + { "4", 4}, + { "raid5", 5}, + { "5", 5}, + { NULL, 0} +}; @@ -0,0 +1,140 @@ + +md_p.h,1316 +#define _MD_P_H16,582 +#define MD_RESERVED_BYTES 44,1414 +#define MD_RESERVED_SECTORS 45,1453 +#define MD_RESERVED_BLOCKS 46,1508 +#define MD_NEW_SIZE_SECTORS(MD_NEW_SIZE_SECTORS48,1570 +#define MD_NEW_SIZE_BLOCKS(MD_NEW_SIZE_BLOCKS49,1659 +#define MD_SB_BYTES 51,1746 +#define MD_SB_WORDS 52,1773 +#define MD_SB_BLOCKS 53,1813 +#define MD_SB_SECTORS 54,1863 +#define MD_SB_GENERIC_OFFSET 59,1960 +#define MD_SB_PERSONALITY_OFFSET 60,1992 +#define MD_SB_DISKS_OFFSET 61,2028 +#define MD_SB_DESCRIPTOR_OFFSET 62,2060 +#define MD_SB_GENERIC_CONSTANT_WORDS 64,2098 +#define MD_SB_GENERIC_STATE_WORDS 65,2138 +#define MD_SB_GENERIC_WORDS 66,2175 +#define MD_SB_PERSONALITY_WORDS 67,2263 +#define MD_SB_DESCRIPTOR_WORDS 68,2299 +#define MD_SB_DISKS 69,2334 +#define MD_SB_DISKS_WORDS 70,2359 +#define MD_SB_RESERVED_WORDS 71,2423 +#define MD_SB_EQUAL_WORDS 72,2553 +#define MD_DISK_FAULTY 77,2691 +#define MD_DISK_ACTIVE 78,2752 +#define MD_DISK_SYNC 79,2814 +#define MD_DISK_REMOVED 80,2878 +typedef struct mdp_device_descriptor_s mdp_device_descriptor_s82,2946 +} mdp_disk_t;mdp_disk_t89,3310 +#define MD_SB_MAGIC 91,3325 +#define MD_SB_CLEAN 96,3390 +#define MD_SB_ERRORS 97,3413 +typedef struct mdp_superblock_s mdp_superblock_s99,3438 +} mdp_super_t;mdp_super_t164,5820 +static inline __u64 md_event(166,5836 + +md_u.h,1118 +#define _MD_U_H16,590 +#define RAID_VERSION 21,634 +#define GET_ARRAY_INFO 22,693 +#define GET_DISK_INFO 23,757 +#define PRINT_RAID_DEBUG 24,819 +#define RAID_AUTORUN 25,865 +#define CLEAR_ARRAY 28,929 +#define ADD_NEW_DISK 29,971 +#define HOT_REMOVE_DISK 30,1032 +#define SET_ARRAY_INFO 31,1078 +#define SET_DISK_INFO 32,1142 +#define WRITE_RAID_INFO 33,1186 +#define UNPROTECT_ARRAY 34,1232 +#define PROTECT_ARRAY 35,1278 +#define HOT_ADD_DISK 36,1322 +#define SET_DISK_FAULTY 37,1365 +#define RUN_ARRAY 40,1424 +#define START_ARRAY 41,1478 +#define STOP_ARRAY 42,1520 +#define STOP_ARRAY_RO 43,1561 +#define RESTART_ARRAY_RW 44,1605 +typedef struct mdu_version_s mdu_version_s46,1652 +} mdu_version_t;mdu_version_t50,1724 +typedef struct mdu_array_info_s mdu_array_info_s52,1742 +} mdu_array_info_t;mdu_array_info_t83,2516 +typedef struct mdu_disk_info_s mdu_disk_info_s85,2537 +} mdu_disk_info_t;mdu_disk_info_t95,2693 +typedef struct mdu_start_info_s mdu_start_info_s97,2713 +} mdu_start_info_t;mdu_start_info_t106,2857 +typedef struct mdu_param_smdu_param_s108,2878 +} mdu_param_t;mdu_param_t113,3014 + +mdctl.h,823 +#define __USE_LARGEFILE6430,1115 +#define MD_MAJOR 47,1491 +extern char short_options[52,1531 +extern struct option long_options[53,1560 +extern char Version[54,1597 +extern char Version[], Usage[54,1597 +extern char Version[], Usage[], Help[54,1597 +extern char Version[], Usage[], Help[], Help_create[54,1597 +extern char Version[], Usage[], Help[], Help_create[], Help_build[54,1597 +extern char Version[], Usage[], Help[], Help_create[], Help_build[], Help_assemble[54,1597 +typedef struct mddev_uuid_s mddev_uuid_s58,1762 +} *mddev_uuid_t;mddev_uuid_t62,1852 +typedef struct mddev_dev_s mddev_dev_s65,1918 +} *mddev_dev_t;mddev_dev_t68,1990 +#define ALGORITHM_LEFT_ASYMMETRIC 73,2044 +#define ALGORITHM_RIGHT_ASYMMETRIC 74,2080 +#define ALGORITHM_LEFT_SYMMETRIC 75,2117 +#define ALGORITHM_RIGHT_SYMMETRIC 76,2152 + +Assemble.c,22 +int Assemble(34,1171 + +Build.c,19 +int Build(32,1135 + +Create.c,20 +int Create(32,1135 + +Detail.c,20 +int Detail(34,1171 + +Examine.c,21 +int Examine(34,1171 + +Manage.c,79 +int Manage_ro(32,1135 +int Manage_runstop(36,1191 +int Manage_subdevs(40,1251 + +ReadMe.c,231 +#define Name 32,1135 +char Version[33,1156 +char short_options[82,3241 +struct option long_options[83,3297 +char Usage[122,4441 +char Help[127,4498 +char Help_create[181,6989 +char Help_build[203,7973 +char Help_assemble[216,8513 + +config.c,102 +char DefaultConfFile[43,1371 +mddev_uuid_t conf_get_uuids(45,1416 +mddev_dev_t conf_get_devs(50,1482 + +mdctl.c,40 +int main(33,1153 +#define O(O131,3313 + +util.c,212 +int parse_uuid(40,1354 +int md_get_version(80,2091 +int get_linux_version(99,2448 +int enough(111,2639 +int same_uuid(127,2889 +void uuid_from_super(137,3018 +int compare_super(151,3295 +int load_super(185,4258 @@ -1,7 +1,12 @@ - check superblock checksum in examine - report "chunk" or "rounding" depending on raid level -- report "linear" instead of "-1" for raid level -- decode ayout depending on raid level +- report "linear" instead of "-1" for raid level DONE +- decode ayout depending on raid level DONE - get Assemble to upgrade devices if force flag. -- --verbose and --force flags.
\ No newline at end of file +- --verbose and --force flags. + +- set md_minor, *_disks for Create +- for create raid5, how to choose between + all working, but not insync + one missing, one spare, insync @@ -7,8 +7,8 @@ else echo $target is not a directory exit 2 fi set `grep '^char Version' ReadMe.c ` -echo version = $6 -base=mdctl-$6.tgz +echo version = $7 +base=mdctl-$7.tgz if [ -f $target/$base ] then echo $target/$base exists. @@ -17,4 +17,4 @@ fi trap "rm $target/$base; exit" 1 2 3 ( cd .. ; tar czvf - mdctl ) > $target/$base chmod a+r $target/$base -ls -l $target/$base
\ No newline at end of file +ls -l $target/$base @@ -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; i<subdevs; i++) @@ -49,6 +49,8 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); #include "md_u.h" +#define Name "mdctl" + extern char short_options[]; extern struct option long_options[]; extern char Version[], Usage[], Help[], Help_create[], Help_build[], Help_assemble[]; @@ -67,13 +69,15 @@ typedef struct mddev_dev_s { struct mddev_dev_s *next; } *mddev_dev_t; -/* - * RAID5 supported algorithms - */ -#define ALGORITHM_LEFT_ASYMMETRIC 0 -#define ALGORITHM_RIGHT_ASYMMETRIC 1 -#define ALGORITHM_LEFT_SYMMETRIC 2 -#define ALGORITHM_RIGHT_SYMMETRIC 3 +typedef struct mapping { + char *name; + int num; +} mapping_t; + +extern char *map_num(mapping_t *map, int num); +extern int map_name(mapping_t *map, char *name); +extern mapping_t r5layout[], pers[]; + extern int Manage_ro(char *devname, int fd, int readonly); @@ -95,9 +99,9 @@ extern int Build(char *mddev, int mdfd, int chunk, int level, extern 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); extern int Detail(char *dev); extern int Examine(char *dev); @@ -105,6 +109,9 @@ extern int Examine(char *dev); extern int md_get_version(int fd); extern int get_linux_version(); extern int parse_uuid(char *str, int uuid[4]); +extern int check_ext2(int fd, char *name); +extern int check_reiser(int fd, char *name); +extern int check_raid(int fd, char *name); extern mddev_uuid_t conf_get_uuids(char *); extern mddev_dev_t conf_get_devs(char *); @@ -88,10 +88,10 @@ int md_get_version(int fd) return -1; if (ioctl(fd, RAID_VERSION, &vers) == 0) - return (vers.major<<16) | (vers.minor<<8) | vers.patchlevel; + return (vers.major*10000) + (vers.minor*100) + vers.patchlevel; if (MAJOR(stb.st_rdev) == MD_MAJOR) - return (36<<8); + return (3600); return -1; } @@ -105,7 +105,7 @@ int get_linux_version() if (sscanf(name.release, "%d.%d.%d", &a,&b,&c)!= 3) return -1; - return (a<<16)+(b<<8)+c; + return (a*1000000)+(b*1000)+c; } int enough(int level, int raid_disks, int avail_disks) @@ -211,7 +211,7 @@ int load_super(int fd, mdp_super_t *super) if (lseek64(fd, offset, 0)< 0LL) return 3; - if (read(fd, &super, sizeof(super)) != sizeof(super)) + if (read(fd, super, sizeof(*super)) != sizeof(*super)) return 4; if (super->md_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<<bsize), ctime(&mtime)); + return 1; +} + +int check_reiser(int fd, char *name) +{ + /* + * superblock is at 64K + * size is 1024; + * Magic string "ReIsErFs" or "ReIsEr2Fs" at 52 + * + */ + unsigned char sb[1024]; + int size; + if (lseek(fd, 64*1024, 0) != 64*1024) + return 0; + if (read(fd, sb, 1024) != 1024) + return 0; + if (strncmp(sb+52, "ReIsErFs",8)!=0 && + strncmp(sb+52, "ReIsEr2Fs",9)!=0) + return 0; + fprintf(stderr, Name ": %s appears to contain a reiserfs file system\n",name); + size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8; + fprintf(stderr, " size = %dK\n", size*4); + + return 1; +} + +int check_raid(int fd, char *name) +{ + mdp_super_t super; + time_t crtime; + if (load_super(fd, &super)) + return 0; + /* Looks like a raid array .. */ + fprintf(stderr, Name ": %s appear to be part of a raid array:\n", + name); + crtime = super.ctime; + fprintf(stderr, " level=%d disks=%d ctime=%s", + super.level, super.raid_disks, ctime(&crtime)); + return 1; +} + + +int ask(char *mesg) +{ + char *add = ""; + int i; + for (i=0; i<5; i++) { + char buf[100]; + fprintf(stderr, "%s%s", mesg, add); + fflush(stderr); + if (fgets(buf, 100, stdin)==NULL) + return 0; + if (buf[0]=='y' || buf[0]=='Y') + return 1; + if (buf[0]=='n' || buf[0]=='N') + return 0; + add = "(y/n) "; + } + fprintf(stderr, Name ": assuming 'no'\n"); + return 0; +} + +char *map_num(mapping_t *map, int num) +{ + while (map->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; +} |