]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Separate sueprblock handling into separate file
authorNeil Brown <neilb@suse.de>
Tue, 3 May 2005 23:44:18 +0000 (23:44 +0000)
committerNeil Brown <neilb@suse.de>
Tue, 3 May 2005 23:44:18 +0000 (23:44 +0000)
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
12 files changed:
Assemble.c
Create.c
Detail.c
Examine.c
Grow.c
Kill.c
Makefile
Query.c
ReadMe.c
mdadm.h
super0.c [new file with mode: 0644]
util.c

index ace5717c310adb7dc932b21dd30bc67756025df9..e762c693e502321a7c1e87d495a07f521714f11b 100644 (file)
@@ -28,8 +28,6 @@
  */
 
 #include       "mdadm.h"
-#include       "md_u.h"
-#include       "md_p.h"
 
 int Assemble(char *mddev, int mdfd,
             mddev_ident_t ident, char *conffile,
@@ -52,11 +50,11 @@ int Assemble(char *mddev, int mdfd,
         * Much of the work of Assemble is in finding and/or
         * checking the disks to make sure they look right.
         *
-        * If mddev is not set, then scan must be and we
+        * If mddev is not set, then scan must be set and we
         *  read through the config file for dev+uuid mapping
         *  We recurse, setting mddev, for each device that
         *    - isn't running
-        *    - has a valid uuid (or any uuid if !uuidset
+        *    - has a valid uuid (or any uuid if !uuidset)
         *
         * If mddev is set, we try to determine state of md.
         *   check version - must be at least 0.90.0
@@ -74,9 +72,9 @@ int Assemble(char *mddev, int mdfd,
         *   Check superblock - discard if bad
         *   Check uuid (set if we don't have one) - discard if no match
         *   Check superblock similarity if we have a superblock - discard if different
-        *   Record events, devicenum, utime
+        *   Record events, devicenum
         * This should give us a list of devices for the array
-        * We should collect the most recent event and utime numbers
+        * We should collect the most recent event number
         *
         * Count disks with recent enough event count
         * While force && !enough disks
@@ -94,14 +92,12 @@ int Assemble(char *mddev, int mdfd,
         */
        int old_linux = 0;
        int vers;
-       mdu_array_info_t array;
-       mdp_super_t first_super, super;
+       void *first_super = NULL, *super = NULL;
        struct {
                char *devname;
                unsigned int major, minor;
                unsigned int oldmajor, oldminor;
                long long events;
-               time_t utime;
                int uptodate;
                int state;
                int raid_disk;
@@ -119,6 +115,7 @@ int Assemble(char *mddev, int mdfd,
        int start_partial_ok = force || devlist==NULL;
        unsigned int num_devs;
        mddev_dev_t tmpdev;
+       struct mdinfo info;
        
        vers = md_get_version(mdfd);
        if (vers <= 0) {
@@ -133,7 +130,7 @@ int Assemble(char *mddev, int mdfd,
        if (get_linux_version() < 2004000)
                old_linux = 1;
 
-       if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) {
+       if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) {
                fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
                        mddev);
                return 1;
@@ -165,12 +162,8 @@ int Assemble(char *mddev, int mdfd,
                num_devs++;
                tmpdev = tmpdev->next;
        }
-       best = malloc(num_devs * sizeof(*best));
        devices = malloc(num_devs * sizeof(*devices));
 
-       first_super.md_magic = 0;
-       for (i=0; i<num_devs; i++)
-               best[i] = -1;
 
        if (verbose)
            fprintf(stderr, Name ": looking for devices for %s\n",
@@ -178,10 +171,8 @@ int Assemble(char *mddev, int mdfd,
 
        while ( devlist) {
                char *devname;
-               int this_uuid[4];
                int dfd;
                struct stat stb;
-               int havesuper=0;
 
                devname = devlist->devname;
                devlist = devlist->next;
@@ -192,6 +183,11 @@ int Assemble(char *mddev, int mdfd,
                                fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
                        continue;
                }
+
+               if (super) {
+                       free(super);
+                       super = NULL;
+               }
                
                dfd = open(devname, O_RDONLY|O_EXCL, 0);
                if (dfd < 0) {
@@ -207,40 +203,39 @@ int Assemble(char *mddev, int mdfd,
                        fprintf(stderr, Name ": %s is not a block device.\n",
                                devname);
                        close(dfd);
-               } else if (load_super(dfd, &super)) {
+               } else if (load_super0(dfd, &super, NULL)) {
                        if (inargv || verbose)
                                fprintf( stderr, Name ": no RAID superblock on %s\n",
                                         devname);
                        close(dfd);
                } else {
-                       havesuper =1;
-                       uuid_from_super(this_uuid, &super);
+                       getinfo_super0(&info, super);
                        close(dfd);
                }
 
                if (ident->uuid_set &&
-                   (!havesuper || same_uuid(this_uuid, ident->uuid)==0)) {
+                   (!super || same_uuid(info.uuid, ident->uuid)==0)) {
                        if (inargv || verbose)
                                fprintf(stderr, Name ": %s has wrong uuid.\n",
                                        devname);
                        continue;
                }
                if (ident->super_minor != UnSet &&
-                   (!havesuper || ident->super_minor != super.md_minor)) {
+                   (!super || ident->super_minor != info.array.md_minor)) {
                        if (inargv || verbose)
                                fprintf(stderr, Name ": %s has wrong super-minor.\n",
                                        devname);
                        continue;
                }
                if (ident->level != UnSet &&
-                   (!havesuper|| ident->level != (int)super.level)) {
+                   (!super|| ident->level != info.array.level)) {
                        if (inargv || verbose)
                                fprintf(stderr, Name ": %s has wrong raid level.\n",
                                        devname);
                        continue;
                }
                if (ident->raid_disks != UnSet &&
-                   (!havesuper || ident->raid_disks!= super.raid_disks)) {
+                   (!super || ident->raid_disks!= info.array.raid_disks)) {
                        if (inargv || verbose)
                                fprintf(stderr, Name ": %s requires wrong number of drives.\n",
                                        devname);
@@ -252,85 +247,34 @@ int Assemble(char *mddev, int mdfd,
                 * then we cannot continue
                 */
 
-               if (!havesuper) {
+               if (!super) {
                        fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
                                devname);
+                       free(first_super);
                        return 1;
                }
-               if (compare_super(&first_super, &super)) {
+               if (compare_super0(&first_super, super)) {
                        fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
                                devname);
+                       free(super);
+                       free(first_super);
                        return 1;
                }
 
-
-               /* this is needed until we get a more relaxed super block format */
-               if (devcnt >= MD_SB_DISKS) {
-                   fprintf(stderr, Name ": ouch - too many devices appear to be in this array. Ignoring %s\n",
-                           devname);
-                   continue;
-               }
-               
                /* looks like a good enough match to update the super block if needed */
                if (update) {
-                       if (strcmp(update, "sparc2.2")==0 ) {
-                               /* 2.2 sparc put the events in the wrong place
-                                * So we copy the tail of the superblock
-                                * up 4 bytes before continuing
-                                */
-                               __u32 *sb32 = (__u32*)&super;
-                               memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
-                                      sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
-                                      (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
-                               fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
-                                        devname);
-                       }
-                       if (strcmp(update, "super-minor") ==0) {
-                               struct stat stb2;
-                               fstat(mdfd, &stb2);
-                               super.md_minor = minor(stb2.st_rdev);
-                               if (verbose)
-                                       fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
-                                               devname, super.md_minor);
-                       }
-                       if (strcmp(update, "summaries") == 0) {
-                               /* set nr_disks, active_disks, working_disks,
-                                * failed_disks, spare_disks based on disks[] 
-                                * array in superblock.
-                                * Also make sure extra slots aren't 'failed'
-                                */
-                               super.nr_disks = super.active_disks =
-                                       super.working_disks = super.failed_disks =
-                                       super.spare_disks = 0;
-                               for (i=0; i < MD_SB_DISKS ; i++) 
-                                       if (super.disks[i].major ||
-                                           super.disks[i].minor) {
-                                               int state = super.disks[i].state;
-                                               if (state & (1<<MD_DISK_REMOVED))
-                                                       continue;
-                                               super.nr_disks++;
-                                               if (state & (1<<MD_DISK_ACTIVE))
-                                                       super.active_disks++;
-                                               if (state & (1<<MD_DISK_FAULTY))
-                                                       super.failed_disks++;
-                                               else
-                                                       super.working_disks++;
-                                               if (state == 0)
-                                                       super.spare_disks++;
-                                       } else if (i >= super.raid_disks && super.disks[i].number == 0)
-                                               super.disks[i].state = 0;
-                       }
-                       if (strcmp(update, "resync") == 0) {
-                               /* make sure resync happens */
-                               super.state &= ~(1<<MD_SB_CLEAN);
-                               super.recovery_cp = 0;
-                       }
-                       super.sb_csum = calc_sb_csum(&super);
+                       /* prepare useful information in info structures */
+                       struct stat stb2;
+                       fstat(mdfd, &stb2);
+                       info.array.md_minor = minor(stb2.st_rdev);
+                       
+                       update_super0(&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_super(dfd, &super))
+                       else if (store_super0(dfd, super))
                                fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
                                        devname);
                        if (dfd >= 0)
@@ -339,23 +283,22 @@ int Assemble(char *mddev, int mdfd,
 
                if (verbose)
                        fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
-                               devname, mddev, super.this_disk.raid_disk);
+                               devname, mddev, info.disk.raid_disk);
                devices[devcnt].devname = devname;
                devices[devcnt].major = major(stb.st_rdev);
                devices[devcnt].minor = minor(stb.st_rdev);
-               devices[devcnt].oldmajor = super.this_disk.major;
-               devices[devcnt].oldminor = super.this_disk.minor;
-               devices[devcnt].events = md_event(&super);
-               devices[devcnt].utime = super.utime;
-               devices[devcnt].raid_disk = super.this_disk.raid_disk;
+               devices[devcnt].oldmajor = info.disk.major;
+               devices[devcnt].oldminor = info.disk.minor;
+               devices[devcnt].events = info.events;
+               devices[devcnt].raid_disk = info.disk.raid_disk;
                devices[devcnt].uptodate = 0;
-               devices[devcnt].state = super.this_disk.state;
+               devices[devcnt].state = info.disk.state;
                if (most_recent < devcnt) {
                        if (devices[devcnt].events
                            > devices[most_recent].events)
                                most_recent = devcnt;
                }
-               if ((int)super.level == -4) 
+               if (info.array.level == -4) 
                        /* with multipath, the raid_disk from the superblock is meaningless */
                        i = devcnt;
                else
@@ -381,11 +324,19 @@ int Assemble(char *mddev, int mdfd,
                devcnt++;
        }
 
+       if (super)
+               free(super);
+       super = NULL;
+
        if (devcnt == 0) {
                fprintf(stderr, Name ": no devices found for %s\n",
                        mddev);
+               free(first_super);
                return 1;
        }
+
+       getinfo_super0(&info, first_super);
+
        /* now we have some devices that might be suitable.
         * I wonder how many
         */
@@ -398,7 +349,7 @@ int Assemble(char *mddev, int mdfd,
                /* note: we ignore error flags in multipath arrays
                 * as they don't make sense
                 */
-               if ((int)first_super.level != -4)
+               if (info.array.level != -4)
                        if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
                                if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
                                        sparecnt++;
@@ -407,20 +358,20 @@ int Assemble(char *mddev, int mdfd,
                if (devices[j].events+event_margin >=
                    devices[most_recent].events) {
                        devices[j].uptodate = 1;
-                       if (i < first_super.raid_disks)
+                       if (i < info.array.raid_disks)
                                okcnt++;
                        else
                                sparecnt++;
                }
        }
-       while (force && !enough(first_super.level, first_super.raid_disks, okcnt)) {
+       while (force && !enough(info.array.level, info.array.raid_disks, okcnt)) {
                /* Choose the newest best drive which is
                 * not up-to-date, update the superblock
                 * and add it.
                 */
                int fd;
                chosen_drive = -1;
-               for (i=0; i<first_super.raid_disks && i < bestcnt; i++) {
+               for (i=0; i<info.array.raid_disks && i < bestcnt; i++) {
                        int j = best[i];
                        if (j>=0 &&
                            !devices[j].uptodate &&
@@ -442,31 +393,29 @@ int Assemble(char *mddev, int mdfd,
                        devices[chosen_drive].events = 0;
                        continue;
                }
-               if (load_super(fd, &super)) {
+               if (load_super0(fd, &super, NULL)) {
                        close(fd);
                        fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
                                devices[chosen_drive].devname);
                        devices[chosen_drive].events = 0;
                        continue;
                }
-               super.events_hi = (devices[most_recent].events>>32)&0xFFFFFFFF;
-               super.events_lo = (devices[most_recent].events)&0xFFFFFFFF;
-               if (super.level == 5 || super.level == 4) {
-                       /* need to force clean */
-                       super.state = (1<<MD_SB_CLEAN);
-               }
-               super.sb_csum = calc_sb_csum(&super);
-/*DRYRUN*/     if (store_super(fd, &super)) {
+               info.events = devices[most_recent].events;
+               update_super0(&info, super, "force", devices[chosen_drive].devname, verbose);
+
+               if (store_super0(fd, super)) {
                        close(fd);
                        fprintf(stderr, Name ": Could not re-write superblock on %s\n",
                                devices[chosen_drive].devname);
                        devices[chosen_drive].events = 0;
+                       free(super);
                        continue;
                }
                close(fd);
                devices[chosen_drive].events = devices[most_recent].events;
                devices[chosen_drive].uptodate = 1;
                okcnt++;
+               free(super);
        }
 
        /* Now we want to look at the superblock which the kernel will base things on
@@ -476,9 +425,11 @@ int Assemble(char *mddev, int mdfd,
         * superblock.
         */
        chosen_drive = -1;
+       super = NULL;
        for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
                int j = best[i];
                int fd;
+
                if (j<0)
                        continue;
                if (!devices[j].uptodate)
@@ -489,7 +440,7 @@ int Assemble(char *mddev, int mdfd,
                                devices[j].devname, strerror(errno));
                        return 1;
                }
-               if (load_super(fd, &super)) {
+               if (load_super0(fd, &super, NULL)) {
                        close(fd);
                        fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
                                devices[j].devname);
@@ -497,12 +448,16 @@ int Assemble(char *mddev, int mdfd,
                }
                close(fd);
        }
-
+       if (super == NULL) {
+               fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
+               return 1;
+       }
+       getinfo_super0(&info, super);
        for (i=0; i<bestcnt; i++) {
                int j = best[i];
                unsigned int desired_state;
 
-               if (i < super.raid_disks)
+               if (i < info.array.raid_disks)
                        desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
                else
                        desired_state = 0;
@@ -511,77 +466,57 @@ int Assemble(char *mddev, int mdfd,
                        continue;
                if (!devices[j].uptodate)
                        continue;
-#if 0
-This doesnt work yet 
-               if (devices[j].major != super.disks[i].major ||
-                   devices[j].minor != super.disks[i].minor) {
-                       change |= 1;
-                       super.disks[i].major = devices[j].major;
-                       super.disks[i].minor = devices[j].minor;
-               }
-#endif 
-               if (devices[j].oldmajor != super.disks[i].major ||
-                   devices[j].oldminor != super.disks[i].minor) {
-                       change |= 2;
-                       super.disks[i].major = devices[j].oldmajor;
-                       super.disks[i].minor = devices[j].oldminor;
-               }
+               info.disk.number = i;
+               info.disk.state = desired_state;
+
                if (devices[j].uptodate &&
-                   (super.disks[i].state != desired_state)) {
+                   update_super0(&info, super, "assemble", NULL, 0)) {
                        if (force) {
                                fprintf(stderr, Name ": "
                                        "clearing FAULTY flag for device %d in %s for %s\n",
                                        j, mddev, devices[j].devname);
-                               super.disks[i].state = desired_state;
-                               change |= 2;
+                               change = 1;
                        } else {
                                fprintf(stderr, Name ": "
                                        "device %d in %s has wrong state in superblock, but %s seems ok\n",
                                        i, mddev, devices[j].devname);
                        }
                }
+#if 0
                if (!devices[j].uptodate &&
                    !(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
                        fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
                                i, mddev);
                }
+#endif
        }
-       if (force && (super.level == 4 || super.level == 5) && 
-           okcnt == super.raid_disks-1) {
-               super.state = (1<< MD_SB_CLEAN);
-               change |= 2;
+       if (force && okcnt == info.array.raid_disks-1) {
+               /* FIXME check event count */
+               change += update_super0(&info, super, "force", 
+                                       devices[chosen_drive].devname, 0);
        }
 
-       if ((force && (change & 2))
-           || (old_linux && (change & 1))) {
+       if (change) {
                int fd;
-               super.sb_csum = calc_sb_csum(&super);
                fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
                if (fd < 0) {
                        fprintf(stderr, Name ": Could open %s for write - cannot Assemble array.\n",
                                devices[chosen_drive].devname);
                        return 1;
                }
-               if (store_super(fd, &super)) {
+               if (store_super0(fd, super)) {
                        close(fd);
                        fprintf(stderr, Name ": Could not re-write superblock on %s\n",
                                devices[chosen_drive].devname);
                        return 1;
                }
                close(fd);
-               change = 0;
        }
 
        /* count number of in-sync devices according to the superblock.
         * We must have this number to start the array without -s or -R
         */
-       req_cnt = 0;
-       for (i=0; i<MD_SB_DISKS; i++)
-               if ((first_super.disks[i].state & (1<<MD_DISK_SYNC)) &&
-                   (first_super.disks[i].state & (1<<MD_DISK_ACTIVE)) &&
-                   !(first_super.disks[i].state & (1<<MD_DISK_FAULTY)))
-                       req_cnt ++;
-                                                                           
+       req_cnt = info.array.working_disks;
 
        /* Almost ready to actually *do* something */
        if (!old_linux) {
@@ -610,28 +545,28 @@ This doesnt work yet
                                                devices[j].devname,
                                                mddev,
                                                strerror(errno));
-                                       if (i < first_super.raid_disks || i == bestcnt)
+                                       if (i < info.array.raid_disks || i == bestcnt)
                                                okcnt--;
                                        else
                                                sparecnt--;
                                } else if (verbose)
                                        fprintf(stderr, Name ": added %s to %s as %d\n",
                                                devices[j].devname, mddev, devices[j].raid_disk);
-                       } else if (verbose && i < first_super.raid_disks)
+                       } else if (verbose && i < info.array.raid_disks)
                                fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
                                        i, mddev);
                }
                
                if (runstop == 1 ||
                    (runstop == 0 && 
-                    ( enough(first_super.level, first_super.raid_disks, okcnt) &&
+                    ( enough(info.array.level, info.array.raid_disks, okcnt) &&
                       (okcnt >= req_cnt || start_partial_ok)
                             ))) {
                        if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
                                fprintf(stderr, Name ": %s has been started with %d drive%s",
                                        mddev, okcnt, okcnt==1?"":"s");
-                               if (okcnt < first_super.raid_disks) 
-                                       fprintf(stderr, " (out of %d)", first_super.raid_disks);
+                               if (okcnt < info.array.raid_disks) 
+                                       fprintf(stderr, " (out of %d)", info.array.raid_disks);
                                if (sparecnt)
                                        fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
                                fprintf(stderr, ".\n");
@@ -649,13 +584,13 @@ This doesnt work yet
                fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
                if (sparecnt)
                        fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
-               if (!enough(first_super.level, first_super.raid_disks, okcnt))
+               if (!enough(info.array.level, info.array.raid_disks, okcnt))
                        fprintf(stderr, " - not enough to start the array.\n");
                else {
-                       if (req_cnt == first_super.raid_disks)
+                       if (req_cnt == info.array.raid_disks)
                                fprintf(stderr, " - need all %d to start it", req_cnt);
                        else
-                               fprintf(stderr, " - need %d of %d to start", req_cnt, first_super.raid_disks);
+                               fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks);
                        fprintf(stderr, " (use --run to insist).\n");
                }
                return 1;
index 66a88d2008bd03a950971048437c753207df4bb6..87a275e2c4f25d83b15acdac458f7c219349074e 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -62,7 +62,8 @@ int Create(char *mddev, int mdfd,
        int first_missing = MD_SB_DISKS*2;
        int missing_disks = 0;
        int insert_point = MD_SB_DISKS*2; /* where to insert a missing drive */
-       mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
+       void *super;
+       int pass;
 
        mdu_array_info_t array;
        
@@ -342,50 +343,70 @@ int Create(char *mddev, int mdfd,
        array.layout = layout;
        array.chunk_size = chunk*1024;
 
-       if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
+       if (ioctl(mdfd, SET_ARRAY_INFO, NULL)) {
                fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
                        mddev, strerror(errno));
                return 1;
        }
-       
-       for (dnum=0, dv = devlist ; dv ; dv=(dv->next)?(dv->next):moved_disk, dnum++) {
-               int fd;
-               struct stat stb;
-               mdu_disk_info_t disk;
 
-               disk.number = dnum;
-               if (dnum == insert_point) {
-                       moved_disk = dv;
-               }
-               disk.raid_disk = disk.number;
-               if (disk.raid_disk < raiddisks)
-                       disk.state = 6; /* active and in sync */
-               else
-                       disk.state = 0;
-               if (dnum == insert_point ||
-                   strcasecmp(dv->devname, "missing")==0) {
-                       disk.major = 0;
-                       disk.minor = 0;
-                       disk.state = 1; /* faulty */
-               } else {
-                       fd = open(dv->devname, O_RDONLY|O_EXCL, 0);
-                       if (fd < 0) {
-                               fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
-                                       dv->devname);
-                               return 1;
+       init_super0(&super, &array);
+
+
+       for (pass=1; pass <=2 ; pass++) {
+               mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
+
+               for (dnum=0, dv = devlist ; dv ;
+                    dv=(dv->next)?(dv->next):moved_disk, dnum++) {
+                       int fd;
+                       struct stat stb;
+                       mdu_disk_info_t disk;
+
+                       disk.number = dnum;
+                       if (dnum == insert_point) {
+                               moved_disk = dv;
                        }
-                       fstat(fd, &stb);
-                       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\n",
-                               dv->devname, strerror(errno));
-                       return 1;
+                       disk.raid_disk = disk.number;
+                       if (disk.raid_disk < raiddisks)
+                               disk.state = 6; /* active and in sync */
+                       else
+                               disk.state = 0;
+                       if (dnum == insert_point ||
+                           strcasecmp(dv->devname, "missing")==0) {
+                               disk.major = 0;
+                               disk.minor = 0;
+                               disk.state = 1; /* faulty */
+                       } else {
+                               fd = open(dv->devname, O_RDONLY|O_EXCL, 0);
+                               if (fd < 0) {
+                                       fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
+                                               dv->devname);
+                                       return 1;
+                               }
+                               fstat(fd, &stb);
+                               disk.major = major(stb.st_rdev);
+                               disk.minor = minor(stb.st_rdev);
+                               close(fd);
+                       }
+                       switch(pass){
+                       case 1:
+                               add_to_super0(super, &disk);
+                               break;
+                       case 2:
+                               write_init_super0(super, &disk, dv->devname);
+
+                               if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
+                                       fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
+                                               dv->devname, strerror(errno));
+                                       free(super);
+                                       return 1;
+                               }
+
+                               break;
+                       }
+                       if (dv == moved_disk && dnum != insert_point) break;
                }
-               if (dv == moved_disk && dnum != insert_point) break;
        }
+       free(super);
 
        /* param is not actually used */
        if (runstop == 1 || subdevs >= raiddisks) {
index 7555a9ace5d4e5682802672e43dc8af226230397..59b091fe149119821288572c32fd6906a5904c7a 100644 (file)
--- a/Detail.c
+++ b/Detail.c
@@ -51,8 +51,7 @@ int Detail(char *dev, int brief, int test)
        int is_rebuilding = 0;
        int failed = 0;
 
-       mdp_super_t super;
-       int have_super = 0;
+       void *super = NULL;
        int rv = test ? 4 : 1;
 
        if (fd < 0) {
@@ -99,16 +98,21 @@ int Detail(char *dev, int brief, int test)
                    disk.minor == 0)
                        continue;
                if ((dv=map_dev(disk.major, disk.minor))) {
-                       if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
+                       if (!super && (disk.state & (1<<MD_DISK_ACTIVE))) {
                                /* try to read the superblock from this device
                                 * to get more info
                                 */
                                int fd2 = open(dv, O_RDONLY);
                                if (fd2 >=0 &&
-                                   load_super(fd2, &super) ==0 &&
-                                   (unsigned long)super.ctime == (unsigned long)array.ctime &&
-                                   (unsigned int)super.level == (unsigned int)array.level)
-                                       have_super = 1;
+                                   load_super0(fd2, &super, NULL) == 0) {
+                                       struct mdinfo info;
+                                       getinfo_super0(&info, super);
+                                       if (info.array.ctime != array.ctime ||
+                                           info.array.level != array.level) {
+                                               free(super);
+                                               super = NULL;
+                                       }
+                               }
                                if (fd2 >= 0) close(fd2);
                        }
                }
@@ -198,15 +202,8 @@ int Detail(char *dev, int brief, int test)
                }
                free_mdstat(ms);
 
-               if (have_super) {
-                       printf("           UUID : ");
-                       if (super.minor_version >= 90)
-                               printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
-                                      super.set_uuid2, super.set_uuid3);
-                       else
-                               printf("%08x", super.set_uuid0);
-                       printf("\n         Events : %d.%d\n\n", super.events_hi, super.events_lo);
-               }
+               if (super)
+                       detail_super0(super);
 
                printf("    Number   Major   Minor   RaidDevice State\n");
        }
@@ -278,14 +275,9 @@ int Detail(char *dev, int brief, int test)
                if (!brief) printf("\n");
        }
        if (spares && brief) printf(" spares=%d", spares);
-       if (have_super && brief) {
-               printf(" UUID=");
-               if (super.minor_version >= 90)
-                       printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
-                              super.set_uuid2, super.set_uuid3);
-               else
-                       printf("%08x", super.set_uuid0);
-       }
+       if (super && brief)
+               brief_detail_super0(super);
+
        if (brief && devices) printf("\n   devices=%s", devices);
        if (brief) printf("\n");
        if (test && (rv&2)) rv &= ~1;
index 79537fa736eca0c6d498a9959b123caf35cf9281..cd79583a827b452045c3ff87c3c7dd6b4a074d09 100644 (file)
--- a/Examine.c
+++ b/Examine.c
@@ -54,18 +54,16 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
         * if devlist==NULL, use conf_get_devs(
         */
        int fd; 
-       time_t atime;
-       mdp_super_t super;
-       int d;
-       char *c;
+       void *super = NULL;
        int rv = 0;
        int err;
-       int spares = 0;
 
        struct array {
-               mdp_super_t super;
+               void *super;
+               struct mdinfo info;
                void *devs;
                struct array *next;
+               int spares;
        } *arrays = NULL;
 
        for (; devlist ; devlist=devlist->next) {
@@ -77,48 +75,21 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                        err = 1;
                }
                else {
-                       err = load_super(fd, &super);
+                       err = load_super0(fd, &super, (brief||scan)?NULL:devlist->devname);
                        close(fd);
                }
-               if (err && (brief||scan))
+               if (err)
                        continue;
                if (err) rv =1;
-               switch(err) {
-               case 1:
-                       fprintf(stderr, Name ": cannot find device size for %s: %s\n",
-                               devlist->devname, strerror(errno));
-                       continue;
-               case 2:
-/*             fprintf(stderr, Name ": %s is too small for md: size is %ld sectors\n",
-               devlist->devname, size);
-*/
-                       fprintf(stderr, Name ": %s is too small for md\n",
-                               devlist->devname);
-                       continue;
-               case 3:
-                       fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
-                               devlist->devname, strerror(errno));
-                       continue;
-               case 4:
-                       fprintf(stderr, Name ": Cannot read superblock on %s\n",
-                               devlist->devname);
-                       continue;
-               case 5:
-                       fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
-                               devlist->devname, MD_SB_MAGIC, super.md_magic);
-                       continue;
-               case 6:
-                       fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
-                               devlist->devname, super.major_version);
-                       continue;
-               }
-    
+
+               if (SparcAdjust)
+                       update_super0(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_super(&ap->super, &super)==0)
+                               if (compare_super0(&ap->super, super)==0)
                                        break;
                        }
                        if (!ap) {
@@ -126,140 +97,37 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                                ap->super = super;
                                ap->devs = dl_head();
                                ap->next = arrays;
+                               ap->spares = 0;
                                arrays = ap;
+                               getinfo_super0(&ap->info, super);
+                       } else {
+                               getinfo_super0(&ap->info, super);
+                               free(super);
                        }
+                       if (!(ap->info.disk.state & MD_DISK_SYNC))
+                               ap->spares++;
                        d = dl_strdup(devlist->devname);
                        dl_add(ap->devs, d);
                } else {
                        printf("%s:\n",devlist->devname);
-                       printf("          Magic : %08x\n", super.md_magic);
-                       printf("        Version : %02d.%02d.%02d\n", super.major_version, super.minor_version,
-                              super.patch_version);
-                       if (super.minor_version >= 90)
-                               printf("           UUID : %08x:%08x:%08x:%08x\n", super.set_uuid0, super.set_uuid1,
-                                      super.set_uuid2, super.set_uuid3);
-                       else
-                               printf("           UUID : %08x\n", super.set_uuid0);
-
-                       atime = super.ctime;
-                       printf("  Creation Time : %.24s\n", ctime(&atime));
-                       c=map_num(pers, super.level);
-                       printf("     Raid Level : %s\n", c?c:"-unknown-");
-                       if (super.level <= 0)
-                               printf("    Device Size : %u%s\n", super.size, human_size((long long)super.size<<10));
-                       printf("   Raid Devices : %d\n", super.raid_disks);
-                       printf("  Total Devices : %d\n", super.nr_disks);
-                       printf("Preferred Minor : %d\n", super.md_minor);
-                       printf("\n");
-                       atime = super.utime;
-                       printf("    Update Time : %.24s\n", ctime(&atime));
-                       printf("          State : %s\n",
-                              (super.state&(1<<MD_SB_CLEAN))?"clean":"active");
-                       printf(" Active Devices : %d\n", super.active_disks);
-                       printf("Working Devices : %d\n", super.working_disks);
-                       printf(" Failed Devices : %d\n", super.failed_disks);
-                       printf("  Spare Devices : %d\n", super.spare_disks);
-                       if (calc_sb_csum(&super) == super.sb_csum)
-                               printf("       Checksum : %x - correct\n", super.sb_csum);
-                       else
-                               printf("       Checksum : %x - expected %lx\n", super.sb_csum, calc_sb_csum(&super));
-                       if (SparcAdjust) {
-                               /* 2.2 sparc put the events in the wrong place
-                                * So we copy the tail of the superblock
-                                * up 4 bytes before continuing
-                                */
-                               __u32 *sb32 = (__u32*)&super;
-                               memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
-                                      sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
-                                      (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
-                               printf (" --- adjusting superblock for 2.2/sparc compatability ---\n");
-                       }
-                       printf("         Events : %d.%d\n", super.events_hi, super.events_lo);
-                       if (super.events_hi == super.cp_events_hi &&
-                           super.events_lo == super.cp_events_lo &&
-                           super.recovery_cp > 0 &&
-                           (super.state & (1<<MD_SB_CLEAN)) == 0 )
-                               printf("Sync checkpoint : %d KB (%d%%)\n", super.recovery_cp/2, super.recovery_cp/(super.size/100*2));
-                       printf("\n");
-                       if (super.level == 5) {
-                               c = map_num(r5layout, super.layout);
-                               printf("         Layout : %s\n", c?c:"-unknown-");
-                       }
-                       if (super.level == 10)
-                               printf("         Layout : near=%d, far=%d\n",
-                                      super.layout&255, (super.layout>>8) & 255);
-
-                       switch(super.level) {
-                       case 0:
-                       case 4:
-                       case 5:
-                               printf("     Chunk Size : %dK\n", super.chunk_size/1024);
-                               break;
-                       case -1:
-                               printf("       Rounding : %dK\n", super.chunk_size/1024);
-                               break;
-                       default: break;         
-                       }
-                       printf("\n");
-                       printf("      Number   Major   Minor   RaidDevice State\n");
-                       for (d= -1; d<(signed int)(super.raid_disks+super.spare_disks); d++) {
-                               mdp_disk_t *dp;
-                               char *dv;
-                               char nb[5];
-                               if (d>=0) dp = &super.disks[d];
-                               else dp = &super.this_disk;
-                               sprintf(nb, "%4d", d);
-                               printf("%4s %5d   %5d    %5d    %5d     ", d < 0 ? "this" :  nb,
-                                      dp->number, dp->major, dp->minor, dp->raid_disk);
-                               if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
-                               if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
-                               if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
-                               if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
-                               if (dp->state == 0) { printf(" spare"); spares++; }
-                               if ((dv=map_dev(dp->major, dp->minor)))
-                                       printf("   %s", dv);
-                               printf("\n");
-                               if (d == -1) printf("\n");
-                       }
-               }
-               if (SparcAdjust == 2) {
-                       printf(" ----- updating superblock on device ----\n");
-                       fd = open(devlist->devname, O_RDWR);
-                       if (fd < 0) {
-                               fprintf(stderr, Name ": cannot open %s to update superblock: %s\n",
-                                       devlist->devname, strerror(errno));
-                               err = 1;
-                       } else {
-                               super.sb_csum = calc_sb_csum(&super);
-                               if (store_super(fd, &super)) {
-                                       fprintf(stderr, Name ": Count not re-write superblock on %s\n",
-                                               devlist->devname);
-                                       err = 1;
-                               }
-                               close(fd);
-                       }
+                       examine_super0(super);
+                       free(super);
                }
        }
        if (brief) {
                struct array *ap;
                for (ap=arrays; ap; ap=ap->next) {
                        char sep='=';
-                       char *c=map_num(pers, ap->super.level);
                        char *d;
-                       printf("ARRAY %s level=%s num-devices=%d UUID=",
-                              get_md_name(ap->super.md_minor),
-                              c?c:"-unknown-", ap->super.raid_disks);
-                       if (spares) printf(" spares=%d", spares);
-                       if (ap->super.minor_version >= 90)
-                               printf("%08x:%08x:%08x:%08x", ap->super.set_uuid0, ap->super.set_uuid1,
-                                      ap->super.set_uuid2, ap->super.set_uuid3);
-                       else
-                               printf("%08x", ap->super.set_uuid0);
-                       printf("\n   devices");
+                       brief_examine_super0(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)) {
                                printf("%c%s", sep, d);
                                sep=',';
                        }
+                       free(ap->super);
+                       /* FIXME free ap */
                        printf("\n");
                }
        }
diff --git a/Grow.c b/Grow.c
index 3f8a1c6634739d2a56e5bcb5861bdf838415b9c1..8de28d407ba5bac7e5328d4b0756be0cd606d782 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -45,20 +45,20 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
         * all other devices.
         * This means that we need to *find* all other devices.
         */
-       mdu_array_info_t array;
-       mdu_disk_info_t disk;
-       mdp_super_t super;
+       struct mdinfo info;
+
+       void *super = NULL;
        struct stat stb;
        int nfd, fd2;
        int d, nd;
        
 
-       if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
+       if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) {
                fprintf(stderr, Name ": cannot get array info for %s\n", devname);
                return 1;
        }
 
-       if (array.level != -1) {
+       if (info.array.level != -1) {
                fprintf(stderr, Name ": can only add devices to linear arrays\n");
                return 1;
        }
@@ -75,7 +75,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                return 1;
        }
        /* now check out all the devices and make sure we can read the superblock */
-       for (d=0 ; d < array.raid_disks ; d++) {
+       for (d=0 ; d < info.array.raid_disks ; d++) {
                mdu_disk_info_t disk;
                char *dv;
 
@@ -96,7 +96,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                        fprintf(stderr, Name ": cannot open device file %s\n", dv);
                        return 1;
                }
-               if (load_super(fd2, &super)) {
+               if (super) free(super);
+               super= NULL;
+               if (load_super0(fd2, &super, NULL)) {
                        fprintf(stderr, Name ": cannot find super block on %s\n", dv);
                        close(fd2);
                        return 1;
@@ -107,27 +109,21 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
         * newdev.
         */
        
-       memset(&super.disks[d], 0, sizeof(super.disks[d]));
-       super.disks[d].number = d;
-       super.disks[d].major = major(stb.st_rdev);
-       super.disks[d].minor = minor(stb.st_rdev);
-       super.disks[d].raid_disk = d;
-       super.disks[d].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
+       info.disk.number = d;
+       info.disk.major = major(stb.st_rdev);
+       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);
 
-       super.this_disk = super.disks[d];
-       super.sb_csum = calc_sb_csum(&super);
-       if (store_super(nfd, &super)) {
+       if (store_super0(nfd, super)) {
                fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
                close(nfd);
                return 1;
        }
-       disk.number = d;
-       disk.major = major(stb.st_rdev);
-       disk.minor = minor(stb.st_rdev);
-       disk.raid_disk = d;
-       disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
        close(nfd);
-       if (ioctl(fd, ADD_NEW_DISK, &disk) != 0) {
+
+       if (ioctl(fd, ADD_NEW_DISK, &info.disk) != 0) {
                fprintf(stderr, Name ": Cannot add new disk to this array\n");
                return 1;
        }
@@ -135,13 +131,13 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
         * Now go through and update all superblocks
         */
 
-       if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
+       if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) {
                fprintf(stderr, Name ": cannot get array info for %s\n", devname);
                return 1;
        }
 
        nd = d;
-       for (d=0 ; d < array.raid_disks ; d++) {
+       for (d=0 ; d < info.array.raid_disks ; d++) {
                mdu_disk_info_t disk;
                char *dv;
 
@@ -162,25 +158,23 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
                        fprintf(stderr, Name ": cannot open device file %s\n", dv);
                        return 1;
                }
-               if (load_super(fd2, &super)) {
+               if (load_super0(fd2, &super, NULL)) {
                        fprintf(stderr, Name ": cannot find super block on %s\n", dv);
                        close(fd);
                        return 1;
                }
-               super.raid_disks = nd+1;
-               super.nr_disks = nd+1;
-               super.active_disks = nd+1;
-               super.working_disks = nd+1;
-               memset(&super.disks[nd], 0, sizeof(super.disks[nd]));
-               super.disks[nd].number = nd;
-               super.disks[nd].major = major(stb.st_rdev);
-               super.disks[nd].minor = minor(stb.st_rdev);
-               super.disks[nd].raid_disk = nd;
-               super.disks[nd].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
-
-               super.this_disk = super.disks[d];
-               super.sb_csum = calc_sb_csum(&super);
-               if (store_super(fd2, &super)) {
+               info.array.raid_disks = nd+1;
+               info.array.nr_disks = nd+1;
+               info.array.active_disks = nd+1;
+               info.array.working_disks = nd+1;
+               info.disk.number = nd;
+               info.disk.major = major(stb.st_rdev);
+               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);
+               
+               if (store_super0(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 9441f73bb43f88ce4733ac7671e7c2cfc9dd94ab..fbda6863a6594c8bacf6aaafd7157767d05975b0 100644 (file)
--- a/Kill.c
+++ b/Kill.c
@@ -41,7 +41,7 @@ int Kill(char *dev, int force)
         * Definitely not safe.
         */
 
-       mdp_super_t super;
+       void *super;
        int fd, rv = 0;
                
        fd = open(dev, O_RDWR|O_EXCL);
@@ -50,32 +50,18 @@ int Kill(char *dev, int force)
                        dev);
                return 1;
        } 
-       rv = load_super(fd, &super);
-       if (force && rv >= 5)
+       rv = load_super0(fd, &super, dev);
+       if (force && rv >= 2)
                rv = 0; /* ignore bad data in superblock */
-       switch(rv) {
-       case 1:
-               fprintf(stderr, Name ": cannot file device size for %s: %s\n",
-                       dev, strerror(errno));
-               break;
-       case 2:
-               fprintf(stderr, Name ": %s is too small for md.\n", dev);
-               break;
-       case 3:
-       case 4:
-               fprintf(stderr, Name ": cannot access superblock on %s.\n", dev);
-               break;
-       case 5:
-       case 6:
-               fprintf(stderr, Name ": %s does not appear to have an MD superblock.\n", dev);
-               break;
-       }
-       if (!rv) {
+       if (rv== 0 || (force && rv >= 2)) {
                memset(&super, 0, sizeof(super));
-               if (store_super(fd, &super)) {
+               if (store_super0(fd, super)) {
                        fprintf(stderr, Name ": Could not zero superblock on %s\n",
                                dev);
                        rv = 1;
+               } else if (rv) {
+                       fprintf(stderr, Name ": superblock zeroed anyway\n");
+                       rv = 0;
                }
        }
        close(fd);
index 8f0547b9d2dbeb9f048bfc8c8c284d6150a29823..38cfcdeeeee8fcba530eed46b521ce0bc813d177 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -58,9 +58,10 @@ MAN5DIR = $(MANDIR)/man5
 MAN8DIR = $(MANDIR)/man8
 
 OBJS =  mdadm.o config.o mdstat.o  ReadMe.o util.o Manage.o Assemble.o Build.o \
-       Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o mdopen.o
+       Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o mdopen.o super0.o
 SRCS =  mdadm.c config.c mdstat.c  ReadMe.c util.c Manage.c Assemble.c Build.c \
-       Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c mdopen.c
+       Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c mdopen.c super0.c
+
 ASSEMBLE_SRCS := mdassemble.c Assemble.c config.c dlink.c util.c
 ifdef MDASSEMBLE_AUTO
 ASSEMBLE_SRCS += mdopen.c mdstat.c
diff --git a/Query.c b/Query.c
index 95d69147a0591b9186ada05aaa5f7d96a33e2182..71aafd84b706ff48d301e43f6bd2549dba102b35 100644 (file)
--- a/Query.c
+++ b/Query.c
@@ -41,8 +41,10 @@ int Query(char *dev)
        int vers;
        int ioctlerr;
        int superror, superrno;
-       mdp_super_t super;
+       struct mdinfo info;
        mdu_array_info_t array;
+       void *super;
+
        unsigned long long larray_size;
        unsigned long array_size;
        struct stat stb;
@@ -60,8 +62,6 @@ int Query(char *dev)
        if (ioctl(fd, GET_ARRAY_INFO, &array)<0)
                ioctlerr = errno;
        else ioctlerr = 0;
-       superror = load_super(fd, &super);
-       superrno = errno;
  
        fstat(fd, &stb);
 
@@ -76,7 +76,6 @@ int Query(char *dev)
                                larray_size <<= 9;
                        } else larray_size = 0;
        }
-       close(fd);
 
        if (vers < 0) 
                printf("%s: is not an md array\n", dev);
@@ -95,35 +94,14 @@ int Query(char *dev)
                       array.raid_disks,
                       array.spare_disks, array.spare_disks==1?"":"s");
        }
-       switch(superror) {
-       case 1:
-               printf("%s: cannot find device size: %s\n",
-                      dev, strerror(superrno));
-               break;
-       case 2:
-               printf("%s: is too small to be an md component.\n",
-                      dev);
-               break;
-       case 3:
-               printf("%s: Cannot seek to superblock: %s\n",
-                      dev, strerror(superrno));
-               break;
-       case 4:
-               printf("%s: Cannot read md superblock.\n",
-                      dev);
-               break;
-       case 5:
-               printf("%s: No md super block found, not an md component.\n",
-                      dev);
-               break;
-       case 6:
-               printf("%s: md superblock present with wrong version: %d\n",
-                      dev, super.major_version);
-               break;
-       default:
+       superror = load_super0(fd, &super, dev);
+       superrno = errno;
+       close(fd);
+       if (superror == 0) {
                /* array might be active... */
-               mddev = get_md_name(super.md_minor);
-               disc.number = super.this_disk.number;
+               getinfo_super0(&info, super);
+               mddev = get_md_name(info.array.md_minor);
+               disc.number = info.disk.number;
                activity = "undetected";
                if (mddev && (fd = open(mddev, O_RDONLY))>=0) {
                        if (md_get_version(fd) >= 9000 &&       
@@ -138,11 +116,10 @@ int Query(char *dev)
                }
                printf("%s: device %d in %d device %s %s md%d.  Use mdadm --examine for more detail.\n",
                       dev, 
-                      super.this_disk.number, super.raid_disks,
+                      info.disk.number, info.array.raid_disks,
                       activity,
-                      map_num(pers, super.level),
-                      super.md_minor);
-               break;
+                      map_num(pers, info.array.level),
+                      info.array.md_minor);
        }
        return 0;
 }
index 78073df05b41366b5e7d09331c86f17f69b03843..00283e99808ce7d7d87723a070d6b6ca7a78238b 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -30,6 +30,7 @@
 #include "mdadm.h"
 
 char Version[] = Name " - v1.11.0 - 11 April 2005\n";
+
 /*
  * File: ReadMe.c
  *
diff --git a/mdadm.h b/mdadm.h
index b7f34d10b074a916e4cd4cc2a2d55184c402518b..6638a342c95faba8b653422533db54e3d51c21a6 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -65,6 +65,14 @@ char *strncpy(char *dest, const char *src, size_t n) __THROW;
 #include       "md_u.h"
 #include       "md_p.h"
 
+/* general information that might be extracted from a superblock */
+struct mdinfo {
+       mdu_array_info_t        array;
+       mdu_disk_info_t         disk;
+       __u64                   events;
+       unsigned int            uuid[4];
+};
+
 #define Name "mdadm"
 
 enum mode {
@@ -211,11 +219,10 @@ extern char *conf_line(FILE *file);
 extern char *conf_word(FILE *file, int allow_key);
 extern void free_line(char *line);
 extern int match_oneof(char *devices, char *devname);
-extern int load_super(int fd, mdp_super_t *super);
 extern void uuid_from_super(int uuid[4], mdp_super_t *super);
 extern int same_uuid(int a[4], int b[4]);
-extern int compare_super(mdp_super_t *first, mdp_super_t *second);
-extern unsigned long calc_sb_csum(mdp_super_t *super);
+/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
+extern unsigned long calc_csum(void *super, int bytes);
 extern int store_super(int fd, mdp_super_t *super);
 extern int enough(int level, int raid_disks, int avail_disks);
 extern int ask(char *mesg);
@@ -255,3 +262,18 @@ 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);
diff --git a/super0.c b/super0.c
new file mode 100644 (file)
index 0000000..a65d1e1
--- /dev/null
+++ b/super0.c
@@ -0,0 +1,539 @@
+/*
+ * mdadm - manage Linux "md" devices aka RAID arrays.
+ *
+ * Copyright (C) 2001-2004 Neil Brown <neilb@cse.unsw.edu.au>
+ *
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *    Author: Neil Brown
+ *    Email: <neilb@cse.unsw.edu.au>
+ *    Paper: Neil Brown
+ *           School of Computer Science and Engineering
+ *           The University of New South Wales
+ *           Sydney, 2052
+ *           Australia
+ */
+
+#include "mdadm.h"
+
+/*
+ * All handling for the 0.90.0 version superblock is in
+ * this file.
+ * This includes:
+ *   - finding, loading, and writing the superblock.
+ *   - initialising a new superblock
+ *   - printing the superblock for --examine
+ *   - printing part of the superblock for --detail
+ * .. other stuff 
+ */
+
+
+static unsigned long calc_sb0_csum(mdp_super_t *super)
+{
+       unsigned long csum = super->sb_csum;
+       unsigned long newcsum;
+       super->sb_csum= 0 ;
+       newcsum = calc_csum(super, MD_SB_BYTES);
+       super->sb_csum = csum;
+       return newcsum;
+}
+
+void examine_super0(void *sbv)
+{
+       mdp_super_t *sb = sbv;
+       time_t atime;
+       int d;
+       char *c;
+
+       printf("          Magic : %08x\n", sb->md_magic);
+       printf("        Version : %02d.%02d.%02d\n", sb->major_version, sb->minor_version,
+              sb->patch_version);
+       if (sb->minor_version >= 90)
+               printf("           UUID : %08x:%08x:%08x:%08x\n", sb->set_uuid0, sb->set_uuid1,
+                      sb->set_uuid2, sb->set_uuid3);
+       else
+               printf("           UUID : %08x\n", sb->set_uuid0);
+
+       atime = sb->ctime;
+       printf("  Creation Time : %.24s\n", ctime(&atime));
+       c=map_num(pers, sb->level);
+       printf("     Raid Level : %s\n", c?c:"-unknown-");
+       if ((int)sb->level >= 0)
+               printf("    Device Size : %d%s\n", sb->size, human_size((long long)sb->size<<10));
+       printf("   Raid Devices : %d\n", sb->raid_disks);
+       printf("  Total Devices : %d\n", sb->nr_disks);
+       printf("Preferred Minor : %d\n", sb->md_minor);
+       printf("\n");
+       atime = sb->utime;
+       printf("    Update Time : %.24s\n", ctime(&atime));
+       printf("          State : %s\n",
+              (sb->state&(1<<MD_SB_CLEAN))?"clean":"active");
+       printf(" Active Devices : %d\n", sb->active_disks);
+       printf("Working Devices : %d\n", sb->working_disks);
+       printf(" Failed Devices : %d\n", sb->failed_disks);
+       printf("  Spare Devices : %d\n", sb->spare_disks);
+       if (calc_sb0_csum(sb) == sb->sb_csum)
+               printf("       Checksum : %x - correct\n", sb->sb_csum);
+       else
+               printf("       Checksum : %x - expected %lx\n", sb->sb_csum, calc_sb0_csum(sb));
+       printf("         Events : %d.%d\n", sb->events_hi, sb->events_lo);
+       printf("\n");
+       if (sb->level == 5) {
+               c = map_num(r5layout, sb->layout);
+               printf("         Layout : %s\n", c?c:"-unknown-");
+       }
+       switch(sb->level) {
+       case 0:
+       case 4:
+       case 5:
+               printf("     Chunk Size : %dK\n", sb->chunk_size/1024);
+               break;
+       case -1:
+               printf("       Rounding : %dK\n", sb->chunk_size/1024);
+               break;
+       default: break;         
+       }
+       printf("\n");
+       printf("      Number   Major   Minor   RaidDevice State\n");
+       for (d= -1; d<(signed int)(sb->raid_disks+sb->spare_disks); d++) {
+               mdp_disk_t *dp;
+               char *dv;
+               char nb[5];
+               if (d>=0) dp = &sb->disks[d];
+               else dp = &sb->this_disk;
+               sprintf(nb, "%4d", d);
+               printf("%4s %5d   %5d    %5d    %5d     ", d < 0 ? "this" :  nb,
+                      dp->number, dp->major, dp->minor, dp->raid_disk);
+               if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
+               if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
+               if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
+               if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
+               if (dp->state == 0) printf(" spare");
+               if ((dv=map_dev(dp->major, dp->minor)))
+                       printf("   %s", dv);
+               printf("\n");
+               if (d == -1) printf("\n");
+       }
+}
+
+void brief_examine_super0(void *sbv)
+{
+       mdp_super_t *sb = sbv;
+       char *c=map_num(pers, sb->level);
+
+       printf("ARRAY %s level=%s num-devices=%d UUID=",
+              get_md_name(sb->md_minor),
+              c?c:"-unknown-", sb->raid_disks);
+       if (sb->minor_version >= 90)
+               printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
+                      sb->set_uuid2, sb->set_uuid3);
+       else
+               printf("%08x", sb->set_uuid0);
+       printf("\n");
+}
+
+void detail_super0(void *sbv)
+{
+       mdp_super_t *sb = sbv;
+       printf("           UUID : ");
+       if (sb->minor_version >= 90)
+               printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
+                      sb->set_uuid2, sb->set_uuid3);
+       else
+               printf("%08x", sb->set_uuid0);
+       printf("\n         Events : %d.%d\n\n", sb->events_hi, sb->events_lo);
+}
+
+void brief_detail_super0(void *sbv)
+{
+       mdp_super_t *sb = sbv;
+       printf(" UUID=");
+       if (sb->minor_version >= 90)
+               printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
+                      sb->set_uuid2, sb->set_uuid3);
+       else
+               printf("%08x", sb->set_uuid0);
+}
+
+void uuid_from_super0(int uuid[4], void * sbv)
+{
+       mdp_super_t *super = sbv;
+       uuid[0] = super->set_uuid0;
+       if (super->minor_version >= 90) {
+               uuid[1] = super->set_uuid1;
+               uuid[2] = super->set_uuid2;
+               uuid[3] = super->set_uuid3;
+       } else {
+               uuid[1] = 0;
+               uuid[2] = 0;
+               uuid[3] = 0;
+       }
+}
+
+void getinfo_super0(struct mdinfo *info, void *sbv)
+{
+       mdp_super_t *sb = sbv;
+       int working = 0;
+       int i;
+
+       info->array.major_version = sb->major_version;
+       info->array.minor_version = sb->minor_version;
+       info->array.patch_version = sb->patch_version;
+       info->array.raid_disks = sb->raid_disks;
+       info->array.level = sb->level;
+       info->array.md_minor = sb->md_minor;
+       info->array.ctime = sb->ctime;
+
+       info->disk.state = sb->this_disk.state;
+       info->disk.major = sb->this_disk.major;
+       info->disk.minor = sb->this_disk.minor;
+       info->disk.raid_disk = sb->this_disk.raid_disk;
+
+       info->events = md_event(sb);
+
+       uuid_from_super0(info->uuid, sbv);
+       
+       /* work_disks is calculated rather than read directly */
+       for (i=0; i < MD_SB_DISKS; i++)
+               if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
+                   (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
+                   !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
+                       working ++;
+       info->array.working_disks = working;
+}
+
+
+int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
+{
+       int rv = 0;
+       mdp_super_t *sb = sbv;
+       if (strcmp(update, "sparc2.2")==0 ) {
+               /* 2.2 sparc put the events in the wrong place
+                * So we copy the tail of the superblock
+                * up 4 bytes before continuing
+                */
+               __u32 *sb32 = (__u32*)sb;
+               memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
+                      sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
+                      (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
+               fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
+                        devname);
+       }
+       if (strcmp(update, "super-minor") ==0) {
+               sb->md_minor = info->array.md_minor;
+               if (verbose)
+                       fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
+                               devname, info->array.md_minor);
+       }
+       if (strcmp(update, "summaries") == 0) {
+               int i;
+               /* set nr_disks, active_disks, working_disks,
+                * failed_disks, spare_disks based on disks[] 
+                * array in superblock.
+                * Also make sure extra slots aren't 'failed'
+                */
+               sb->nr_disks = sb->active_disks =
+                       sb->working_disks = sb->failed_disks =
+                       sb->spare_disks = 0;
+               for (i=0; i < MD_SB_DISKS ; i++) 
+                       if (sb->disks[i].major ||
+                           sb->disks[i].minor) {
+                               int state = sb->disks[i].state;
+                               if (state & (1<<MD_DISK_REMOVED))
+                                       continue;
+                               sb->nr_disks++;
+                               if (state & (1<<MD_DISK_ACTIVE))
+                                       sb->active_disks++;
+                               if (state & (1<<MD_DISK_FAULTY))
+                                       sb->failed_disks++;
+                               else
+                                       sb->working_disks++;
+                               if (state == 0)
+                                       sb->spare_disks++;
+                       } else if (i >= sb->raid_disks && sb->disks[i].number == 0)
+                               sb->disks[i].state = 0;
+       }
+       if (strcmp(update, "force")==0) {
+               sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
+               sb->events_lo = (info->events) & 0xFFFFFFFF;
+               if (sb->level == 5 || sb->level == 4 || sb->level == 6)
+                       /* need to force clean */
+                       sb->state |= (1 << MD_SB_CLEAN);
+       }
+       if (strcmp(update, "assemble")==0) {
+               int d = info->disk.number;
+               if (sb->disks[d].state != info->disk.state) {
+                       sb->disks[d].state = info->disk.state;
+                       rv = 1;
+               }
+       }
+       if (strcmp(update, "newdev") == 0) {
+               int d = info->disk.number;
+               memset(&sb->disks[d], 0, sizeof(sb->disks[d]));
+               sb->disks[d].number = d;
+               sb->disks[d].major = info->disk.major;
+               sb->disks[d].minor = info->disk.minor;
+               sb->disks[d].raid_disk = info->disk.raid_disk;
+               sb->disks[d].state = info->disk.state;
+               sb->this_disk = sb->disks[d];
+       }
+       if (strcmp(update, "grow") == 0) {
+               sb->raid_disks = info->array.raid_disks;
+               sb->nr_disks = info->array.nr_disks;
+               sb->active_disks = info->array.active_disks;
+               sb->working_disks = info->array.working_disks;
+               memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
+               sb->disks[info->disk.number].number = info->disk.number;
+               sb->disks[info->disk.number].major = info->disk.major;
+               sb->disks[info->disk.number].minor = info->disk.minor;
+               sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
+               sb->disks[info->disk.number].state = info->disk.state;
+               if (sb->this_disk.number == info->disk.number)
+                       sb->this_disk = sb->disks[info->disk.number];
+       }
+       if (strcmp(update, "resync") == 0) {
+               /* make sure resync happens */
+               sb->state &= ~(1<<MD_SB_CLEAN);
+               sb->recovery_cp = 0;
+       }
+
+       sb->sb_csum = calc_sb0_csum(sb);
+       return rv;
+}
+
+__u64 event_super0(void *sbv)
+{
+       mdp_super_t *sb = sbv;
+       return md_event(sb);
+}
+
+
+
+void init_super0(void **sbp, mdu_array_info_t *info)
+{
+       mdp_super_t *sb = malloc(MD_SB_BYTES);
+       memset(sb, 0, MD_SB_BYTES);
+
+       sb->md_magic = MD_SB_MAGIC;
+       sb->major_version = 0;
+       sb->minor_version = 90;
+       sb->patch_version = 0;
+       sb->gvalid_words = 0; /* ignored */
+       sb->set_uuid0 = random();
+       sb->ctime = time(0);
+       sb->level = info->level;
+       sb->size = info->size;
+       sb->nr_disks = info->nr_disks;
+       sb->raid_disks = info->raid_disks;
+       sb->md_minor = info->md_minor;
+       sb->not_persistent = 0;
+       sb->set_uuid1 = random();
+       sb->set_uuid2 = random();
+       sb->set_uuid3 = random();
+
+       sb->utime = sb->ctime;
+       sb->state = info->state;
+       sb->active_disks = info->active_disks;
+       sb->working_disks = info->working_disks;
+       sb->failed_disks = info->failed_disks;
+       sb->events_hi = 0;
+       sb->events_lo = 1;
+
+       sb->layout = info->layout;
+       sb->chunk_size = info->chunk_size;
+
+       *sbp = sb;
+}
+
+/* Add a device to the superblock being created */
+void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
+{
+       mdp_super_t *sb = sbv;
+       mdp_disk_t *dk = &sb->disks[dinfo->number];
+       
+       dk->number = dinfo->number;
+       dk->major = dinfo->major;
+       dk->minor = dinfo->minor;
+       dk->raid_disk = dinfo->raid_disk;
+       dk->state = dinfo->state;
+}
+
+int store_super0(int fd, mdp_super_t *super)
+{
+       unsigned long size;
+       unsigned long long dsize;
+       unsigned long long offset;
+    
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size))
+                       return 1;
+               else
+                       dsize = ((unsigned long long)size)<<9;
+       }
+
+       if (dsize < MD_RESERVED_SECTORS*2)
+               return 2;
+       
+       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
+
+       offset *= 512;
+
+       if (lseek64(fd, offset, 0)< 0LL)
+               return 3;
+
+       if (write(fd, super, sizeof(*super)) != sizeof(*super))
+               return 4;
+
+       return 0;
+}
+
+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);
+       int rv;
+
+       if (fd < 0) {
+               fprintf(stderr, Name ": Failed to open %s to write superblock\n", devname);
+               return -1;
+       }
+
+       sb->this_disk = sb->disks[dinfo->number];
+       sb->sb_csum = calc_sb0_csum(sb);
+       rv = store_super0(fd, sb);
+       close(fd);
+       if (rv)
+               fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
+       return rv;
+}
+
+int compare_super0(void **firstp, void *secondv)
+{
+       /*
+        * return:
+        *  0 same, or first was empty, and second was copied
+        *  1 second had wrong number
+        *  2 wrong uuid
+        *  3 wrong other info
+        */
+       mdp_super_t *first = *firstp;
+       mdp_super_t *second = secondv;
+
+       int uuid1[4], uuid2[4];
+       if (second->md_magic != MD_SB_MAGIC)
+               return 1;
+       if (!first) {
+               first = malloc(MD_SB_BYTES);
+               memcpy(first, second, MD_SB_BYTES);
+               *firstp = first;
+               return 0;
+       }
+
+       uuid_from_super0(uuid1, first);
+       uuid_from_super0(uuid2, second);
+       if (!same_uuid(uuid1, uuid2))
+               return 2;
+       if (first->major_version != second->major_version ||
+           first->minor_version != second->minor_version ||
+           first->patch_version != second->patch_version ||
+           first->gvalid_words  != second->gvalid_words  ||
+           first->ctime         != second->ctime         ||
+           first->level         != second->level         ||
+           first->size          != second->size          ||
+           first->raid_disks    != second->raid_disks    )
+               return 3;
+
+       return 0;
+}
+
+
+int load_super0(int fd, void **sbp, char *devname)
+{
+       /* try to read in the superblock
+        * Return:
+        *  0 on success
+        *  1 on cannot get superblock
+        *  2 on superblock meaningless
+        */
+       unsigned long size;
+       unsigned long long dsize;
+       unsigned long long offset;
+       mdp_super_t *super;
+    
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size)) {
+                       if (devname)
+                               fprintf(stderr, Name ": cannot find device size for %s: %s\n",
+                                       devname, strerror(errno));
+                       return 1;
+               } else
+                       dsize = size << 9;
+       }
+
+       if (dsize < MD_RESERVED_SECTORS*2) {
+               if (devname)
+                       fprintf(stderr, Name ": %s is too small for md: size is %ld sectors.\n",
+                               devname, size);
+               return 1;
+       }
+       
+       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
+
+       offset *= 512;
+
+       ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
+
+       if (lseek64(fd, offset, 0)< 0LL) {
+               if (devname)
+                       fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
+                               devname, strerror(errno));
+               return 1;
+       }
+
+       super = malloc(MD_SB_BYTES);
+
+       if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
+               if (devname)
+                       fprintf(stderr, Name ": Cannot read superblock on %s\n",
+                               devname);
+               free(super);
+               return 1;
+       }
+
+       if (super->md_magic != MD_SB_MAGIC) {
+               if (devname)
+                       fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
+                               devname, MD_SB_MAGIC, super->md_magic);
+               free(super);
+               return 2;
+       }
+
+       if (super->major_version != 0) {
+               if (devname)
+                       fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
+                               devname, super->major_version);
+               free(super);
+               return 2;
+       }
+       *sbp = super;
+       return 0;
+}
diff --git a/util.c b/util.c
index d5e2910c60cf242606bd04ad401b4ee125c650d7..e9bce2a177f61f8d52c06caec17cc6f2fc770543 100644 (file)
--- a/util.c
+++ b/util.c
@@ -150,140 +150,6 @@ int same_uuid(int a[4], int b[4])
     return 0;
 }
 
-void uuid_from_super(int uuid[4], mdp_super_t *super)
-{
-    uuid[0] = super->set_uuid0;
-    if (super->minor_version >= 90) {
-       uuid[1] = super->set_uuid1;
-       uuid[2] = super->set_uuid2;
-       uuid[3] = super->set_uuid3;
-    } else {
-       uuid[1] = 0;
-       uuid[2] = 0;
-       uuid[3] = 0;
-    }
-}
-
-int compare_super(mdp_super_t *first, mdp_super_t *second)
-{
-    /*
-     * return:
-     *  0 same, or first was empty, and second was copied
-     *  1 second had wrong number
-     *  2 wrong uuid
-     *  3 wrong other info
-     */
-    int uuid1[4], uuid2[4];
-    if (second->md_magic != MD_SB_MAGIC)
-       return 1;
-    if (first-> md_magic != MD_SB_MAGIC) {
-       memcpy(first, second, sizeof(*first));
-       return 0;
-    }
-
-    uuid_from_super(uuid1, first);
-    uuid_from_super(uuid2, second);
-    if (!same_uuid(uuid1, uuid2))
-       return 2;
-    if (first->major_version != second->major_version ||
-       first->minor_version != second->minor_version ||
-       first->patch_version != second->patch_version ||
-       first->gvalid_words  != second->gvalid_words  ||
-       first->ctime         != second->ctime         ||
-       first->level         != second->level         ||
-       first->size          != second->size          ||
-       first->raid_disks    != second->raid_disks    )
-       return 3;
-
-    return 0;
-}
-
-int load_super(int fd, mdp_super_t *super)
-{
-       /* try to read in the superblock
-        *
-        * return
-        *   0 - success
-        *   1 - no block size
-        *   2 - too small
-        *   3 - no seek
-        *   4 - no read
-        *   5 - no magic
-        *   6 - wrong major version
-        */
-       unsigned long size;
-       unsigned long long dsize;
-       unsigned long long offset;
-    
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-       {
-               if (ioctl(fd, BLKGETSIZE, &size))
-                       return 1;
-               else
-                       dsize = size << 9;
-       }
-
-       if (dsize < MD_RESERVED_SECTORS*2)
-               return 2;
-       
-       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-
-       offset *= 512;
-
-       ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
-
-       if (lseek64(fd, offset, 0)< 0LL)
-               return 3;
-
-       if (read(fd, super, sizeof(*super)) != sizeof(*super))
-               return 4;
-
-       if (super->md_magic != MD_SB_MAGIC)
-               return 5;
-
-       if (super->major_version != 0)
-               return 6;
-       return 0;
-}
-
-int store_super(int fd, mdp_super_t *super)
-{
-       unsigned long size;
-       unsigned long long dsize;
-       
-       long long offset;
-    
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-       {
-               if (ioctl(fd, BLKGETSIZE, &size))
-                       return 1;
-               else
-                       dsize = ((unsigned long long)size) << 9;
-       }
-
-       if (dsize < MD_RESERVED_SECTORS*2)
-               return 2;
-       
-       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-
-       offset *= 512;
-
-       if (lseek64(fd, offset, 0)< 0LL)
-               return 3;
-
-       if (write(fd, super, sizeof(*super)) != sizeof(*super))
-               return 4;
-
-       fsync(fd);
-       return 0;
-}
-    
-
-
 int check_ext2(int fd, char *name)
 {
        /*
@@ -339,18 +205,25 @@ 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)
 {
-       mdp_super_t super;
+       void *super;
+       struct mdinfo info;
        time_t crtime;
-       if (load_super(fd, &super))
+       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);
-       crtime = super.ctime;
+       getinfo_super0(&info, super);
+       free(super);
+       crtime = info.array.ctime;
        fprintf(stderr, "    level=%d devices=%d ctime=%s",
-               super.level, super.raid_disks, ctime(&crtime));
+               info.array.level, info.array.raid_disks, ctime(&crtime));
        return 1;
 }
 
@@ -506,19 +379,16 @@ char *map_dev(int major, int minor)
 
 #endif
 
-unsigned long calc_sb_csum(mdp_super_t *super)
+unsigned long calc_csum(void *super, int bytes)
 {
-        unsigned int  oldcsum = super->sb_csum;
        unsigned long long newcsum = 0;
-       unsigned long csum;
        int i;
-       unsigned int *superc = (int*) super;
-       super->sb_csum = 0;
+       unsigned int csum;
+       unsigned int *superc = (unsigned int*) super;
 
-       for(i=0; i<MD_SB_BYTES/4; i++)
+       for(i=0; i<bytes/4; i++)
                newcsum+= superc[i];
        csum = (newcsum& 0xffffffff) + (newcsum>>32);
-       super->sb_csum = oldcsum;
        return csum;
 }