mdctl-v0.3 mdctl-v0.3
authorNeil Brown <neilb@suse.de>
Thu, 14 Jun 2001 05:33:53 +0000 (05:33 +0000)
committerNeil Brown <neilb@suse.de>
Thu, 14 Jun 2001 05:33:53 +0000 (05:33 +0000)
13 files changed:
Assemble.c
Create.c
Detail.c
Examine.c
Makefile
Manage.c
ReadMe.c
TAGS [new file with mode: 0644]
TODO
makedist
mdctl.c
mdctl.h
util.c

index 504bde7..fdaff09 100644 (file)
@@ -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;
                }
index dda54fd..ac776c2 100644 (file)
--- a/Create.c
+++ b/Create.c
  */
 
 #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, &param)) {
+                       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;
 }
index 9f81e04..3349c3a 100644 (file)
--- 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;
                }
index ea223c6..f2498ec 100644 (file)
--- 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");
index 4fe9ba8..0168923 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -42,3 +42,6 @@ clean :
 
 dist : clean
        ./makedist
+
+TAGS :
+       etags *.h *.c
index 302a425..7357339 100644 (file)
--- a/Manage.c
+++ b/Manage.c
  */
 
 #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, &param)) {
+                       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;
+       
 }
index e07cc42..9bee800 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -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}
+};
diff --git a/TAGS b/TAGS
new file mode 100644 (file)
index 0000000..bceb7ad
--- /dev/null
+++ b/TAGS
@@ -0,0 +1,140 @@
+\f
+md_p.h,1316
+#define _MD_P_H\7f16,582
+#define MD_RESERVED_BYTES      \7f44,1414
+#define MD_RESERVED_SECTORS    \7f45,1453
+#define MD_RESERVED_BLOCKS     \7f46,1508
+#define MD_NEW_SIZE_SECTORS(\7fMD_NEW_SIZE_SECTORS\ 148,1570
+#define MD_NEW_SIZE_BLOCKS(\7fMD_NEW_SIZE_BLOCKS\ 149,1659
+#define MD_SB_BYTES    \7f51,1746
+#define MD_SB_WORDS    \7f52,1773
+#define MD_SB_BLOCKS   \7f53,1813
+#define MD_SB_SECTORS  \7f54,1863
+#define        MD_SB_GENERIC_OFFSET    \7f59,1960
+#define MD_SB_PERSONALITY_OFFSET       \7f60,1992
+#define MD_SB_DISKS_OFFSET     \7f61,2028
+#define MD_SB_DESCRIPTOR_OFFSET        \7f62,2060
+#define MD_SB_GENERIC_CONSTANT_WORDS   \7f64,2098
+#define MD_SB_GENERIC_STATE_WORDS      \7f65,2138
+#define MD_SB_GENERIC_WORDS    \7f66,2175
+#define MD_SB_PERSONALITY_WORDS        \7f67,2263
+#define MD_SB_DESCRIPTOR_WORDS \7f68,2299
+#define MD_SB_DISKS    \7f69,2334
+#define MD_SB_DISKS_WORDS      \7f70,2359
+#define MD_SB_RESERVED_WORDS   \7f71,2423
+#define MD_SB_EQUAL_WORDS      \7f72,2553
+#define MD_DISK_FAULTY \7f77,2691
+#define MD_DISK_ACTIVE \7f78,2752
+#define MD_DISK_SYNC   \7f79,2814
+#define MD_DISK_REMOVED        \7f80,2878
+typedef struct mdp_device_descriptor_s \7fmdp_device_descriptor_s\ 182,2946
+} mdp_disk_t;\7fmdp_disk_t\ 189,3310
+#define MD_SB_MAGIC    \7f91,3325
+#define MD_SB_CLEAN    \7f96,3390
+#define MD_SB_ERRORS   \7f97,3413
+typedef struct mdp_superblock_s \7fmdp_superblock_s\ 199,3438
+} mdp_super_t;\7fmdp_super_t\ 1164,5820
+static inline __u64 md_event(\7f166,5836
+\f
+md_u.h,1118
+#define _MD_U_H\7f16,590
+#define RAID_VERSION   \7f21,634
+#define GET_ARRAY_INFO \7f22,693
+#define GET_DISK_INFO  \7f23,757
+#define PRINT_RAID_DEBUG       \7f24,819
+#define RAID_AUTORUN   \7f25,865
+#define CLEAR_ARRAY    \7f28,929
+#define ADD_NEW_DISK   \7f29,971
+#define HOT_REMOVE_DISK        \7f30,1032
+#define SET_ARRAY_INFO \7f31,1078
+#define SET_DISK_INFO  \7f32,1142
+#define WRITE_RAID_INFO        \7f33,1186
+#define UNPROTECT_ARRAY        \7f34,1232
+#define PROTECT_ARRAY  \7f35,1278
+#define HOT_ADD_DISK   \7f36,1322
+#define SET_DISK_FAULTY        \7f37,1365
+#define RUN_ARRAY      \7f40,1424
+#define START_ARRAY    \7f41,1478
+#define STOP_ARRAY     \7f42,1520
+#define STOP_ARRAY_RO  \7f43,1561
+#define RESTART_ARRAY_RW       \7f44,1605
+typedef struct mdu_version_s \7fmdu_version_s\ 146,1652
+} mdu_version_t;\7fmdu_version_t\ 150,1724
+typedef struct mdu_array_info_s \7fmdu_array_info_s\ 152,1742
+} mdu_array_info_t;\7fmdu_array_info_t\ 183,2516
+typedef struct mdu_disk_info_s \7fmdu_disk_info_s\ 185,2537
+} mdu_disk_info_t;\7fmdu_disk_info_t\ 195,2693
+typedef struct mdu_start_info_s \7fmdu_start_info_s\ 197,2713
+} mdu_start_info_t;\7fmdu_start_info_t\ 1106,2857
+typedef struct mdu_param_s\7fmdu_param_s\ 1108,2878
+} mdu_param_t;\7fmdu_param_t\ 1113,3014
+\f
+mdctl.h,823
+#define        __USE_LARGEFILE64\7f30,1115
+#define        MD_MAJOR \7f47,1491
+extern char short_options[\7f52,1531
+extern struct option long_options[\7f53,1560
+extern char Version[\7f54,1597
+extern char Version[], Usage[\7f54,1597
+extern char Version[], Usage[], Help[\7f54,1597
+extern char Version[], Usage[], Help[], Help_create[\7f54,1597
+extern char Version[], Usage[], Help[], Help_create[], Help_build[\7f54,1597
+extern char Version[], Usage[], Help[], Help_create[], Help_build[], Help_assemble[\7f54,1597
+typedef struct mddev_uuid_s \7fmddev_uuid_s\ 158,1762
+} *mddev_uuid_t;\7fmddev_uuid_t\ 162,1852
+typedef struct mddev_dev_s \7fmddev_dev_s\ 165,1918
+} *mddev_dev_t;\7fmddev_dev_t\ 168,1990
+#define ALGORITHM_LEFT_ASYMMETRIC      \7f73,2044
+#define ALGORITHM_RIGHT_ASYMMETRIC     \7f74,2080
+#define ALGORITHM_LEFT_SYMMETRIC       \7f75,2117
+#define ALGORITHM_RIGHT_SYMMETRIC      \7f76,2152
+\f
+Assemble.c,22
+int Assemble(\7f34,1171
+\f
+Build.c,19
+int Build(\7f32,1135
+\f
+Create.c,20
+int Create(\7f32,1135
+\f
+Detail.c,20
+int Detail(\7f34,1171
+\f
+Examine.c,21
+int Examine(\7f34,1171
+\f
+Manage.c,79
+int Manage_ro(\7f32,1135
+int Manage_runstop(\7f36,1191
+int Manage_subdevs(\7f40,1251
+\f
+ReadMe.c,231
+#define Name \7f32,1135
+char Version[\7f33,1156
+char short_options[\7f82,3241
+struct option long_options[\7f83,3297
+char Usage[\7f122,4441
+char Help[\7f127,4498
+char Help_create[\7f181,6989
+char Help_build[\7f203,7973
+char Help_assemble[\7f216,8513
+\f
+config.c,102
+char DefaultConfFile[\7f43,1371
+mddev_uuid_t conf_get_uuids(\7f45,1416
+mddev_dev_t conf_get_devs(\7f50,1482
+\f
+mdctl.c,40
+int main(\7f33,1153
+#define O(\7fO\ 1131,3313
+\f
+util.c,212
+int parse_uuid(\7f40,1354
+int md_get_version(\7f80,2091
+int get_linux_version(\7f99,2448
+int enough(\7f111,2639
+int same_uuid(\7f127,2889
+void uuid_from_super(\7f137,3018
+int compare_super(\7f151,3295
+int load_super(\7f185,4258
diff --git a/TODO b/TODO
index 62dab1c..f093277 100644 (file)
--- a/TODO
+++ b/TODO
@@ -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
index 5b6db54..789a80a 100755 (executable)
--- a/makedist
+++ b/makedist
@@ -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
diff --git a/mdctl.c b/mdctl.c
index a2ece91..5a16646 100644 (file)
--- 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; i<subdevs; i++)
diff --git a/mdctl.h b/mdctl.h
index 7e7c389..0e3b917 100644 (file)
--- a/mdctl.h
+++ b/mdctl.h
@@ -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 *);
diff --git a/util.c b/util.c
index bd7f1d8..bb370dd 100644 (file)
--- a/util.c
+++ b/util.c
@@ -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;
+}