]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add a 'super-switch' so that different format superblocks can be used.
authorNeil Brown <neilb@suse.de>
Tue, 3 May 2005 23:44:32 +0000 (23:44 +0000)
committerNeil Brown <neilb@suse.de>
Tue, 3 May 2005 23:44:32 +0000 (23:44 +0000)
This includes:
  adding --metadata= option to choose metadata format
  adding metadata= word to config file.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
13 files changed:
Assemble.c
Create.c
Detail.c
Examine.c
Grow.c
Kill.c
Query.c
ReadMe.c
config.c
mdadm.c
mdadm.h
super0.c
util.c

index e762c693e502321a7c1e87d495a07f521714f11b..3c0986171097a6cfe1af929f2b51c51ce4ff739d 100644 (file)
@@ -29,7 +29,7 @@
 
 #include       "mdadm.h"
 
-int Assemble(char *mddev, int mdfd,
+int Assemble(struct superswitch *ss, char *mddev, int mdfd,
             mddev_ident_t ident, char *conffile,
             mddev_dev_t devlist,
             int readonly, int runstop,
@@ -164,6 +164,7 @@ int Assemble(char *mddev, int mdfd,
        }
        devices = malloc(num_devs * sizeof(*devices));
 
+       if (!ss && ident->ss) ss = ident->ss;
 
        if (verbose)
            fprintf(stderr, Name ": looking for devices for %s\n",
@@ -173,6 +174,7 @@ int Assemble(char *mddev, int mdfd,
                char *devname;
                int dfd;
                struct stat stb;
+               struct superswitch *tss = ss;
 
                devname = devlist->devname;
                devlist = devlist->next;
@@ -203,13 +205,16 @@ int Assemble(char *mddev, int mdfd,
                        fprintf(stderr, Name ": %s is not a block device.\n",
                                devname);
                        close(dfd);
-               } else if (load_super0(dfd, &super, NULL)) {
+               } else if (!tss && (tss = guess_super(dfd, NULL)) == NULL) {
+                       if (inargv || verbose)
+                               fprintf(stderr, Name ": no recogniseable superblock\n");
+               } else if (tss->load_super(dfd, &super, NULL)) {
                        if (inargv || verbose)
                                fprintf( stderr, Name ": no RAID superblock on %s\n",
                                         devname);
                        close(dfd);
                } else {
-                       getinfo_super0(&info, super);
+                       tss->getinfo_super(&info, super);
                        close(dfd);
                }
 
@@ -253,7 +258,8 @@ int Assemble(char *mddev, int mdfd,
                        free(first_super);
                        return 1;
                }
-               if (compare_super0(&first_super, super)) {
+               ss = tss; /* commit to this format, if haven't already */
+               if (ss->compare_super(&first_super, super)) {
                        fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
                                devname);
                        free(super);
@@ -268,13 +274,13 @@ int Assemble(char *mddev, int mdfd,
                        fstat(mdfd, &stb2);
                        info.array.md_minor = minor(stb2.st_rdev);
                        
-                       update_super0(&info, super, update, devname, verbose);
+                       ss->update_super(&info, super, update, devname, verbose);
                        
                        dfd = open(devname, O_RDWR|O_EXCL, 0);
                        if (dfd < 0) 
                                fprintf(stderr, Name ": Cannot open %s for superblock update\n",
                                        devname);
-                       else if (store_super0(dfd, super))
+                       else if (ss->store_super(dfd, super))
                                fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
                                        devname);
                        if (dfd >= 0)
@@ -335,7 +341,7 @@ int Assemble(char *mddev, int mdfd,
                return 1;
        }
 
-       getinfo_super0(&info, first_super);
+       ss->getinfo_super(&info, first_super);
 
        /* now we have some devices that might be suitable.
         * I wonder how many
@@ -393,7 +399,7 @@ int Assemble(char *mddev, int mdfd,
                        devices[chosen_drive].events = 0;
                        continue;
                }
-               if (load_super0(fd, &super, NULL)) {
+               if (ss->load_super(fd, &super, NULL)) {
                        close(fd);
                        fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
                                devices[chosen_drive].devname);
@@ -401,9 +407,9 @@ int Assemble(char *mddev, int mdfd,
                        continue;
                }
                info.events = devices[most_recent].events;
-               update_super0(&info, super, "force", devices[chosen_drive].devname, verbose);
+               ss->update_super(&info, super, "force", devices[chosen_drive].devname, verbose);
 
-               if (store_super0(fd, super)) {
+               if (ss->store_super(fd, super)) {
                        close(fd);
                        fprintf(stderr, Name ": Could not re-write superblock on %s\n",
                                devices[chosen_drive].devname);
@@ -440,7 +446,7 @@ int Assemble(char *mddev, int mdfd,
                                devices[j].devname, strerror(errno));
                        return 1;
                }
-               if (load_super0(fd, &super, NULL)) {
+               if (ss->load_super(fd, &super, NULL)) {
                        close(fd);
                        fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
                                devices[j].devname);
@@ -452,7 +458,7 @@ int Assemble(char *mddev, int mdfd,
                fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
                return 1;
        }
-       getinfo_super0(&info, super);
+       ss->getinfo_super(&info, super);
        for (i=0; i<bestcnt; i++) {
                int j = best[i];
                unsigned int desired_state;
@@ -470,7 +476,7 @@ int Assemble(char *mddev, int mdfd,
                info.disk.state = desired_state;
 
                if (devices[j].uptodate &&
-                   update_super0(&info, super, "assemble", NULL, 0)) {
+                   ss->update_super(&info, super, "assemble", NULL, 0)) {
                        if (force) {
                                fprintf(stderr, Name ": "
                                        "clearing FAULTY flag for device %d in %s for %s\n",
@@ -492,7 +498,7 @@ int Assemble(char *mddev, int mdfd,
        }
        if (force && okcnt == info.array.raid_disks-1) {
                /* FIXME check event count */
-               change += update_super0(&info, super, "force", 
+               change += ss->update_super(&info, super, "force", 
                                        devices[chosen_drive].devname, 0);
        }
 
@@ -504,7 +510,7 @@ int Assemble(char *mddev, int mdfd,
                                devices[chosen_drive].devname);
                        return 1;
                }
-               if (store_super0(fd, super)) {
+               if (ss->store_super(fd, super)) {
                        close(fd);
                        fprintf(stderr, Name ": Could not re-write superblock on %s\n",
                                devices[chosen_drive].devname);
index 87a275e2c4f25d83b15acdac458f7c219349074e..15a7de8711de3ed26c1ace9e4a3903842b9ec27a 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -31,7 +31,7 @@
 #include       "md_u.h"
 #include       "md_p.h"
 
-int Create(char *mddev, int mdfd,
+int Create(struct superswitch *ss, char *mddev, int mdfd,
           int chunk, int level, int layout, unsigned long size, int raiddisks, int sparedisks,
           int subdevs, mddev_dev_t devlist,
           int runstop, int verbose, int force)
@@ -349,7 +349,7 @@ int Create(char *mddev, int mdfd,
                return 1;
        }
 
-       init_super0(&super, &array);
+       ss->init_super(&super, &array);
 
 
        for (pass=1; pass <=2 ; pass++) {
@@ -389,10 +389,10 @@ int Create(char *mddev, int mdfd,
                        }
                        switch(pass){
                        case 1:
-                               add_to_super0(super, &disk);
+                               ss->add_to_super(super, &disk);
                                break;
                        case 2:
-                               write_init_super0(super, &disk, dv->devname);
+                               ss->write_init_super(super, &disk, dv->devname);
 
                                if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
                                        fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
index 59b091fe149119821288572c32fd6906a5904c7a..2f3fc7ff38827fbd74a15988d4d25b50b0adcd97 100644 (file)
--- a/Detail.c
+++ b/Detail.c
@@ -50,6 +50,7 @@ int Detail(char *dev, int brief, int test)
        int is_26 = get_linux_version() >= 2006000;
        int is_rebuilding = 0;
        int failed = 0;
+       struct superswitch *ss = NULL;
 
        void *super = NULL;
        int rv = test ? 4 : 1;
@@ -82,6 +83,8 @@ int Detail(char *dev, int brief, int test)
                close(fd);
                return rv;
        }
+       ss = super_by_version(array.major_version);
+
        if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
                stb.st_rdev = 0;
        rv = 0;
@@ -103,10 +106,10 @@ int Detail(char *dev, int brief, int test)
                                 * to get more info
                                 */
                                int fd2 = open(dv, O_RDONLY);
-                               if (fd2 >=0 &&
-                                   load_super0(fd2, &super, NULL) == 0) {
+                               if (fd2 >=0 && ss &&
+                                   ss->load_super(fd2, &super, NULL) == 0) {
                                        struct mdinfo info;
-                                       getinfo_super0(&info, super);
+                                       ss->getinfo_super(&info, super);
                                        if (info.array.ctime != array.ctime ||
                                            info.array.level != array.level) {
                                                free(super);
@@ -202,8 +205,8 @@ int Detail(char *dev, int brief, int test)
                }
                free_mdstat(ms);
 
-               if (super)
-                       detail_super0(super);
+               if (super && ss)
+                       ss->detail_super(super);
 
                printf("    Number   Major   Minor   RaidDevice State\n");
        }
@@ -275,8 +278,8 @@ int Detail(char *dev, int brief, int test)
                if (!brief) printf("\n");
        }
        if (spares && brief) printf(" spares=%d", spares);
-       if (super && brief)
-               brief_detail_super0(super);
+       if (super && brief && ss)
+               ss->brief_detail_super(super);
 
        if (brief && devices) printf("\n   devices=%s", devices);
        if (brief) printf("\n");
index cd79583a827b452045c3ff87c3c7dd6b4a074d09..8081b66079b2d318e105d5976fcd587f045bcb0b 100644 (file)
--- a/Examine.c
+++ b/Examine.c
@@ -60,6 +60,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
 
        struct array {
                void *super;
+               struct superswitch *ss;
                struct mdinfo info;
                void *devs;
                struct array *next;
@@ -67,6 +68,8 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
        } *arrays = NULL;
 
        for (; devlist ; devlist=devlist->next) {
+               struct superswitch *ss;
+
                fd = open(devlist->devname, O_RDONLY);
                if (fd < 0) {
                        if (!scan)
@@ -75,7 +78,11 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                        err = 1;
                }
                else {
-                       err = load_super0(fd, &super, (brief||scan)?NULL:devlist->devname);
+                       ss = guess_super(fd, devlist->devname);
+                       if (ss)
+                               err = ss->load_super(fd, &super, (brief||scan)?NULL:devlist->devname);
+                       else
+                               err = 1;
                        close(fd);
                }
                if (err)
@@ -83,13 +90,13 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                if (err) rv =1;
 
                if (SparcAdjust)
-                       update_super0(NULL, super, "sparc2.2", devlist->devname, 0);
+                       ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0);
                /* Ok, its good enough to try, though the checksum could be wrong */
                if (brief) {
                        struct array *ap;
                        char *d;
                        for (ap=arrays; ap; ap=ap->next) {
-                               if (compare_super0(&ap->super, super)==0)
+                               if (ss == ap->ss && ss->compare_super(&ap->super, super)==0)
                                        break;
                        }
                        if (!ap) {
@@ -98,10 +105,11 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                                ap->devs = dl_head();
                                ap->next = arrays;
                                ap->spares = 0;
+                               ap->ss = ss;
                                arrays = ap;
-                               getinfo_super0(&ap->info, super);
+                               ss->getinfo_super(&ap->info, super);
                        } else {
-                               getinfo_super0(&ap->info, super);
+                               ss->getinfo_super(&ap->info, super);
                                free(super);
                        }
                        if (!(ap->info.disk.state & MD_DISK_SYNC))
@@ -110,7 +118,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                        dl_add(ap->devs, d);
                } else {
                        printf("%s:\n",devlist->devname);
-                       examine_super0(super);
+                       ss->examine_super(super);
                        free(super);
                }
        }
@@ -119,7 +127,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                for (ap=arrays; ap; ap=ap->next) {
                        char sep='=';
                        char *d;
-                       brief_examine_super0(ap->super);
+                       ap->ss->brief_examine_super(ap->super);
                        if (ap->spares) printf("   spares=%d", ap->spares);
                        printf("   devices");
                        for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
diff --git a/Grow.c b/Grow.c
index 8de28d407ba5bac7e5328d4b0756be0cd606d782..ec2eb55aee43315625b091aafe74273ed57977d6 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -51,6 +51,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
        struct stat stb;
        int nfd, fd2;
        int d, nd;
+       struct superswitch *ss = NULL;
        
 
        if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) {
@@ -58,6 +59,12 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                return 1;
        }
 
+       ss = super_by_version(info.array.major_version);
+       if (!ss) {
+               fprintf(stderr, Name ": cannot handle arrays with superblock version %d\n", info.array.major_version);
+               return 1;
+       }
+
        if (info.array.level != -1) {
                fprintf(stderr, Name ": can only add devices to linear arrays\n");
                return 1;
@@ -98,7 +105,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                }
                if (super) free(super);
                super= NULL;
-               if (load_super0(fd2, &super, NULL)) {
+               if (ss->load_super(fd2, &super, NULL)) {
                        fprintf(stderr, Name ": cannot find super block on %s\n", dv);
                        close(fd2);
                        return 1;
@@ -114,9 +121,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
        info.disk.minor = minor(stb.st_rdev);
        info.disk.raid_disk = d;
        info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
-       update_super0(&info, super, "grow", newdev, 0);
+       ss->update_super(&info, super, "grow", newdev, 0);
 
-       if (store_super0(nfd, super)) {
+       if (ss->store_super(nfd, super)) {
                fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
                close(nfd);
                return 1;
@@ -158,7 +165,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                        fprintf(stderr, Name ": cannot open device file %s\n", dv);
                        return 1;
                }
-               if (load_super0(fd2, &super, NULL)) {
+               if (ss->load_super(fd2, &super, NULL)) {
                        fprintf(stderr, Name ": cannot find super block on %s\n", dv);
                        close(fd);
                        return 1;
@@ -172,9 +179,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                info.disk.minor = minor(stb.st_rdev);
                info.disk.raid_disk = nd;
                info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
-               update_super0(&info, super, "grow", dv, 0);
+               ss->update_super(&info, super, "grow", dv, 0);
                
-               if (store_super0(fd2, super)) {
+               if (ss->store_super(fd2, super)) {
                        fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
                        close(fd2);
                        return 1;
diff --git a/Kill.c b/Kill.c
index fbda6863a6594c8bacf6aaafd7157767d05975b0..b20c28e0ed6c86ef1f8cbccfd2a2de9b98afd499 100644 (file)
--- a/Kill.c
+++ b/Kill.c
@@ -43,19 +43,28 @@ int Kill(char *dev, int force)
 
        void *super;
        int fd, rv = 0;
+       struct superswitch *ss;
                
        fd = open(dev, O_RDWR|O_EXCL);
        if (fd < 0) {
                fprintf(stderr, Name ": Couldn't open %s for write - not zeroing\n",
                        dev);
                return 1;
-       } 
-       rv = load_super0(fd, &super, dev);
+       }
+       ss = guess_super(fd, dev);
+       if (ss == NULL) {
+               fprintf(stderr, Name ": Unrecognised md component device - %s\n", dev);
+               return 1;
+       }
+       rv = ss->load_super(fd, &super, dev);
        if (force && rv >= 2)
                rv = 0; /* ignore bad data in superblock */
        if (rv== 0 || (force && rv >= 2)) {
-               memset(&super, 0, sizeof(super));
-               if (store_super0(fd, super)) {
+               mdu_array_info_t info;
+               info.major_version = -1; /* zero superblock */
+               free(super);
+               ss->init_super(&super, &info);
+               if (ss->store_super(fd, super)) {
                        fprintf(stderr, Name ": Could not zero superblock on %s\n",
                                dev);
                        rv = 1;
diff --git a/Query.c b/Query.c
index 71aafd84b706ff48d301e43f6bd2549dba102b35..88df3214b835de0b90a6f1995d4da28367385524 100644 (file)
--- a/Query.c
+++ b/Query.c
@@ -44,6 +44,7 @@ int Query(char *dev)
        struct mdinfo info;
        mdu_array_info_t array;
        void *super;
+       struct superswitch *ss = NULL;
 
        unsigned long long larray_size;
        unsigned long array_size;
@@ -94,12 +95,16 @@ int Query(char *dev)
                       array.raid_disks,
                       array.spare_disks, array.spare_disks==1?"":"s");
        }
-       superror = load_super0(fd, &super, dev);
-       superrno = errno;
+       ss = guess_super(fd, dev);
+       if (ss) {
+               superror = ss->load_super(fd, &super, dev);
+               superrno = errno;
+       } else 
+               superror = -1;
        close(fd);
        if (superror == 0) {
                /* array might be active... */
-               getinfo_super0(&info, super);
+               ss->getinfo_super(&info, super);
                mddev = get_md_name(info.array.md_minor);
                disc.number = info.disk.number;
                activity = "undetected";
index 00283e99808ce7d7d87723a070d6b6ca7a78238b..367bc0b7e677b861eb4455af178d63d59db4cedd 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -91,7 +91,7 @@ char Version[] = Name " - v1.11.0 - 11 April 2005\n";
  *     At the time if writing, there is only minimal support.
  */
 
-char short_options[]="-ABCDEFGQhVvbc:i:l:p:m:n:x:u:c:d:z:U:sa::rfRSow1t";
+char short_options[]="-ABCDEFGQhVvbc:i:l:p:m:n:x:u:c:d:z:U:sa::rfRSow1te:";
 struct option long_options[] = {
     {"manage",    0, 0, '@'},
     {"misc",      0, 0, '#'},
@@ -127,6 +127,7 @@ struct option long_options[] = {
     {"size",     1, 0, 'z'},
     {"auto",     2, 0, 'a'}, /* also for --assemble */
     {"assume-clean",0,0, 3 },
+    {"metadata",  1, 0, 'e'}, /* superblock format */
 
     /* For assemble */
     {"uuid",      1, 0, 'u'},
index 0aac1a0b0cde7a712c9d09078a8f157ba0c30bca..f3a749c07de1c9bea07c68c9bdae3a90ccc434a6 100644 (file)
--- a/config.c
+++ b/config.c
@@ -328,6 +328,17 @@ void arrayline(char *line)
                } else if (strncasecmp(w, "spares=", 7) == 0 ) {
                        /* for warning if not all spares present */
                        mis.spare_disks = atoi(w+7);
+               } else if (strncasecmp(w, "metadata=", 9) == 0) {
+                       /* style of metadata on the devices. */
+                       int i;
+                       
+                       for(i=0; superlist[i]; i++) 
+                               if (superlist[i]->match_metadata_desc(w+9)) {
+                                       mis.ss = superlist[i];
+                                       break;
+                               }
+                       if (!mis.ss)
+                               fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
                } else if (strncasecmp(w, "auto=", 5) == 0 ) {
                        /* whether to create device special files as needed */
                        if (strcasecmp(w+5, "no")==0)
diff --git a/mdadm.c b/mdadm.c
index daf24123ab40d430a71540da078170001b92fbc9..b738fadd5a0ea664b46016e3b7456f8507f8b789 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -32,7 +32,6 @@
 #include <ctype.h>
 
 
-
 int main(int argc, char *argv[])
 {
        int mode = 0;
@@ -41,6 +40,7 @@ int main(int argc, char *argv[])
        char *help_text;
        char *c;
        int rv;
+       int i;
 
        int chunk = 0;
        int size = -1;
@@ -81,6 +81,7 @@ int main(int argc, char *argv[])
        int daemonise = 0;
        char *pidfile = NULL;
        int oneshot = 0;
+       struct superswitch *ss = NULL;
 
        int copies;
 
@@ -273,6 +274,24 @@ int main(int argc, char *argv[])
                        }
                        continue;
 
+               case O(CREATE,'e'):
+               case O(ASSEMBLE,'e'):
+               case O(MISC,'e'): /* set metadata (superblock) information */
+                       if (ss) {
+                               fprintf(stderr, Name ": metadata information already given\n");
+                               exit(2);
+                       }
+                       for(i=0; superlist[i]; i++) 
+                               if (superlist[i]->match_metadata_desc(optarg)) {
+                                       ss = superlist[i];
+                                       break;
+                               }
+                       if (!ss) {
+                               fprintf(stderr, Name ": unrecognised metadata identifier: %s\n", optarg);
+                               exit(2);
+                       }
+                       continue;
+
                case O(GROW,'z'):
                case O(CREATE,'z'): /* size */
                        if (size >= 0) {
@@ -736,14 +755,14 @@ int main(int argc, char *argv[])
                                if (mdfd < 0)
                                        rv |= 1;
                                else {
-                                       rv |= Assemble(devlist->devname, mdfd, array_ident, configfile,
+                                       rv |= Assemble(ss, devlist->devname, mdfd, array_ident, configfile,
                                                       NULL,
                                                       readonly, runstop, update, verbose, force);
                                        close(mdfd);
                                }
                        }
                } else if (!scan)
-                       rv = Assemble(devlist->devname, mdfd, &ident, configfile,
+                       rv = Assemble(ss, devlist->devname, mdfd, &ident, configfile,
                                      devlist->next,
                                      readonly, runstop, update, verbose, force);
                else if (devs_found>0) {
@@ -764,7 +783,7 @@ int main(int argc, char *argv[])
                                        rv |= 1;
                                        continue;
                                }
-                               rv |= Assemble(dv->devname, mdfd, array_ident, configfile,
+                               rv |= Assemble(ss, dv->devname, mdfd, array_ident, configfile,
                                               NULL,
                                               readonly, runstop, update, verbose, force);
                                close(mdfd);
@@ -786,7 +805,7 @@ int main(int argc, char *argv[])
                                                /* already assembled, skip */
                                                ;
                                        else
-                                               rv |= Assemble(array_list->devname, mdfd,
+                                               rv |= Assemble(ss, array_list->devname, mdfd,
                                                               array_list, configfile,
                                                               NULL,
                                                               readonly, runstop, NULL, verbose, force);
@@ -798,7 +817,19 @@ int main(int argc, char *argv[])
                rv = Build(devlist->devname, mdfd, chunk, level, layout, raiddisks, devlist->next, assume_clean);
                break;
        case CREATE:
-               rv = Create(devlist->devname, mdfd, chunk, level, layout, size<0 ? 0 : size,
+               if (ss == NULL) {
+                       for(i=0; superlist[i]; i++) 
+                               if (superlist[i]->match_metadata_desc("default")) {
+                                       ss = superlist[i];
+                                       break;
+                               }
+               }
+               if (!ss) {
+                       fprintf(stderr, Name ": internal error - no default metadata style\n");
+                       exit(2);
+               }
+
+               rv = Create(ss, devlist->devname, mdfd, chunk, level, layout, size<0 ? 0 : size,
                            raiddisks, sparedisks,
                            devs_found-1, devlist->next, runstop, verbose, force);
                break;
diff --git a/mdadm.h b/mdadm.h
index 6638a342c95faba8b653422533db54e3d51c21a6..491d9075993538e7baf81cd6dbc70b44b61f4c2d 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -116,6 +116,7 @@ typedef struct mddev_ident_s {
        int     level;
        unsigned int raid_disks;
        unsigned int spare_disks;
+       struct superswitch *ss;
        int     autof;          /* 1 for normal, 2 for partitioned */
        char    *spare_group;
 
@@ -163,6 +164,28 @@ extern mapping_t r5layout[], pers[], modes[], faultylayout[];
 extern char *map_dev(int major, int minor);
 
 
+extern struct superswitch {
+       void (*examine_super)(void *sbv);
+       void (*brief_examine_super)(void *sbv);
+       void (*detail_super)(void *sbv);
+       void (*brief_detail_super)(void *sbv);
+       void (*uuid_from_super)(int uuid[4], void *sbv);
+       void (*getinfo_super)(struct mdinfo *info, void *sbv);
+       int (*update_super)(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose);
+       __u64 (*event_super)(void *sbv);
+       void (*init_super)(void **sbp, mdu_array_info_t *info);
+       void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
+       int (*store_super)(int fd, void *sbv);
+       int (*write_init_super)(void *sbv, mdu_disk_info_t *dinfo, char *devname);
+       int (*compare_super)(void **firstp, void *secondv);
+       int (*load_super)(int fd, void **sbp, char *devname);
+       int (*match_metadata_desc)(char *arg);
+} super0, *superlist[];
+
+extern struct superswitch *super_by_version(int vers);
+extern struct superswitch *guess_super(int fd, char *dev);
+
+
 extern int Manage_ro(char *devname, int fd, int readonly);
 extern int Manage_runstop(char *devname, int fd, int runstop);
 extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
@@ -172,7 +195,7 @@ extern int Manage_subdevs(char *devname, int fd,
 extern int Grow_Add_device(char *devname, int fd, char *newdev);
 
 
-extern int Assemble(char *mddev, int mdfd,
+extern int Assemble(struct superswitch *ss, char *mddev, int mdfd,
                    mddev_ident_t ident,
                    char *conffile,
                    mddev_dev_t devlist,
@@ -185,7 +208,7 @@ extern int Build(char *mddev, int mdfd, int chunk, int level, int layout,
                 mddev_dev_t devlist, int assume_clean);
 
 
-extern int Create(char *mddev, int mdfd,
+extern int Create(struct superswitch *ss, char *mddev, int mdfd,
                  int chunk, int level, int layout, unsigned long size, int raiddisks, int sparedisks,
                  int subdevs, mddev_dev_t devlist,
                  int runstop, int verbose, int force);
@@ -262,18 +285,3 @@ extern int open_mddev(char *dev, int autof);
 
 #define        ModeMask        0x1f
 #define        ModeShift       5
-
-extern void examine_super0(void *sbv);
-extern void brief_examine_super0(void *sbv);
-extern void detail_super0(void *sbv);
-extern void brief_detail_super0(void *sbv);
-extern void getinfo_super0(struct mdinfo *info, void *sbv);
-extern int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose);
-extern __u64 event_super0(void *sbv);
-extern void uuid_from_super0(int uuid[4], void * sbv);
-extern void init_super0(void **sbv, mdu_array_info_t *info);
-extern void add_to_super0(void *sbp, mdu_disk_info_t *dinfo);
-extern int store_super0(int fd, mdp_super_t *super);
-extern int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname);
-extern int load_super0(int fd, void **super, char *devname);
-extern int compare_super0(void **first, void *second);
index a65d1e1449275bd30ab273c0be5c79b5e0f98ab7..4cd2cc3dc3560544b0135c4f28865d09e7f0e5e1 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -51,7 +51,7 @@ static unsigned long calc_sb0_csum(mdp_super_t *super)
        return newcsum;
 }
 
-void examine_super0(void *sbv)
+static void examine_super0(void *sbv)
 {
        mdp_super_t *sb = sbv;
        time_t atime;
@@ -129,7 +129,7 @@ void examine_super0(void *sbv)
        }
 }
 
-void brief_examine_super0(void *sbv)
+static void brief_examine_super0(void *sbv)
 {
        mdp_super_t *sb = sbv;
        char *c=map_num(pers, sb->level);
@@ -145,7 +145,7 @@ void brief_examine_super0(void *sbv)
        printf("\n");
 }
 
-void detail_super0(void *sbv)
+static void detail_super0(void *sbv)
 {
        mdp_super_t *sb = sbv;
        printf("           UUID : ");
@@ -157,7 +157,7 @@ void detail_super0(void *sbv)
        printf("\n         Events : %d.%d\n\n", sb->events_hi, sb->events_lo);
 }
 
-void brief_detail_super0(void *sbv)
+static void brief_detail_super0(void *sbv)
 {
        mdp_super_t *sb = sbv;
        printf(" UUID=");
@@ -168,7 +168,7 @@ void brief_detail_super0(void *sbv)
                printf("%08x", sb->set_uuid0);
 }
 
-void uuid_from_super0(int uuid[4], void * sbv)
+static void uuid_from_super0(int uuid[4], void * sbv)
 {
        mdp_super_t *super = sbv;
        uuid[0] = super->set_uuid0;
@@ -183,7 +183,7 @@ void uuid_from_super0(int uuid[4], void * sbv)
        }
 }
 
-void getinfo_super0(struct mdinfo *info, void *sbv)
+static void getinfo_super0(struct mdinfo *info, void *sbv)
 {
        mdp_super_t *sb = sbv;
        int working = 0;
@@ -216,7 +216,7 @@ void getinfo_super0(struct mdinfo *info, void *sbv)
 }
 
 
-int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
+static int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
 {
        int rv = 0;
        mdp_super_t *sb = sbv;
@@ -314,7 +314,7 @@ int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, i
        return rv;
 }
 
-__u64 event_super0(void *sbv)
+static __u64 event_super0(void *sbv)
 {
        mdp_super_t *sb = sbv;
        return md_event(sb);
@@ -322,11 +322,16 @@ __u64 event_super0(void *sbv)
 
 
 
-void init_super0(void **sbp, mdu_array_info_t *info)
+static void init_super0(void **sbp, mdu_array_info_t *info)
 {
        mdp_super_t *sb = malloc(MD_SB_BYTES);
        memset(sb, 0, MD_SB_BYTES);
 
+       if (info->major_version == -1) {
+               /* zeroing the superblock */
+               return;
+       }
+
        sb->md_magic = MD_SB_MAGIC;
        sb->major_version = 0;
        sb->minor_version = 90;
@@ -359,7 +364,7 @@ void init_super0(void **sbp, mdu_array_info_t *info)
 }
 
 /* Add a device to the superblock being created */
-void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
+static void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
 {
        mdp_super_t *sb = sbv;
        mdp_disk_t *dk = &sb->disks[dinfo->number];
@@ -371,11 +376,12 @@ void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
        dk->state = dinfo->state;
 }
 
-int store_super0(int fd, mdp_super_t *super)
+static int store_super0(int fd, void *sbv)
 {
        unsigned long size;
        unsigned long long dsize;
        unsigned long long offset;
+       mdp_super_t *super = sbv;
     
 #ifdef BLKGETSIZE64
        if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
@@ -403,7 +409,7 @@ int store_super0(int fd, mdp_super_t *super)
        return 0;
 }
 
-int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname)
+static int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname)
 {
        mdp_super_t *sb = sbv;
        int fd = open(devname, O_RDWR, O_EXCL);
@@ -423,7 +429,7 @@ int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname)
        return rv;
 }
 
-int compare_super0(void **firstp, void *secondv)
+static int compare_super0(void **firstp, void *secondv)
 {
        /*
         * return:
@@ -463,7 +469,7 @@ int compare_super0(void **firstp, void *secondv)
 }
 
 
-int load_super0(int fd, void **sbp, char *devname)
+static int load_super0(int fd, void **sbp, char *devname)
 {
        /* try to read in the superblock
         * Return:
@@ -537,3 +543,31 @@ int load_super0(int fd, void **sbp, char *devname)
        *sbp = super;
        return 0;
 }
+
+static int match_metadata_desc0(char *arg)
+{
+       if (strcmp(arg, "0") == 0 ||
+           strcmp(arg, "0.90") == 0 ||
+           strcmp(arg, "default") == 0
+               )
+               return 1;
+       return 0;
+}
+
+struct superswitch super0 = {
+       .examine_super = examine_super0,
+       .brief_examine_super = brief_examine_super0,
+       .detail_super = detail_super0,
+       .brief_detail_super = brief_detail_super0,
+       .uuid_from_super = uuid_from_super0,
+       .getinfo_super = getinfo_super0,
+       .update_super = update_super0,
+       .event_super = event_super0,
+       .init_super = init_super0,
+       .add_to_super = add_to_super0,
+       .store_super = store_super0,
+       .write_init_super = write_init_super0,
+       .compare_super = compare_super0,
+       .load_super = load_super0,
+       .match_metadata_desc = match_metadata_desc0,
+};
diff --git a/util.c b/util.c
index e9bce2a177f61f8d52c06caec17cc6f2fc770543..f243d884cdd6f6e7f571a89ef384a9e340a25ef6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -205,26 +205,27 @@ int check_reiser(int fd, char *name)
        return 1;
 }
 
-int load_super(int fd, void **sbp, int vers)
-{
-       return load_super0(fd, sbp, NULL);
-}
 int check_raid(int fd, char *name)
 {
        void *super;
        struct mdinfo info;
        time_t crtime;
-       if (load_super(fd, &super, -1))
-               return 0;
-       /* Looks like a raid array .. */
-       fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
-               name);
-       getinfo_super0(&info, super);
-       free(super);
-       crtime = info.array.ctime;
-       fprintf(stderr, "    level=%d devices=%d ctime=%s",
-               info.array.level, info.array.raid_disks, ctime(&crtime));
-       return 1;
+
+       int i;
+       for (i=0; superlist[i]; i++) {
+               if (superlist[i]->load_super(fd, &super, name))
+                       continue;
+               /* Looks like a raid array .. */
+               fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
+                       name);
+               superlist[i]->getinfo_super(&info, super);
+               free(super);
+               crtime = info.array.ctime;
+               fprintf(stderr, "    level=%d devices=%d ctime=%s",
+                       info.array.level, info.array.raid_disks, ctime(&crtime));
+               return 1;
+       }
+       return 0;
 }
 
 
@@ -521,3 +522,42 @@ void put_md_name(char *name)
        if (strncmp(name, "/dev/.tmp.md", 12)==0)
                unlink(name);
 }
+
+
+
+
+struct superswitch *superlist[] = { &super0, NULL };
+
+struct superswitch *super_by_version(int vers)
+{
+       if (vers == 0) return &super0;
+       return NULL;
+}
+
+struct superswitch *guess_super(int fd, char *dev)
+{
+       /* try each load_super to find the best match,
+        * and return the best superswitch
+        */
+       struct superswitch *best = NULL, *ss;
+       int bestrv = 0;
+       void *sbp = NULL;
+       int i;
+
+       for (i=0 ; superlist[i]; i++) {
+               int rv;
+               ss = superlist[i];
+               rv = ss->load_super(fd, &sbp, NULL);
+               if (rv == 0) {
+                       free(sbp);
+                       return ss;
+               }
+               if (rv > bestrv) {
+                       bestrv  = rv;
+                       best = ss;
+               }
+       }
+       if (bestrv > 2) /* FIXME */
+               return best;
+       return NULL;
+}