]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Fix parsing of /dev/md/N in is_standard
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index f243d884cdd6f6e7f571a89ef384a9e340a25ef6..8febfd2c0ab6e0ff5a3aa23b7ac4d0c912b22221 100644 (file)
--- a/util.c
+++ b/util.c
@@ -195,8 +195,8 @@ int check_reiser(int fd, char *name)
                return 0;
        if (read(fd, sb, 1024) != 1024)
                return 0;
-       if (strncmp(sb+52, "ReIsErFs",8)!=0 &&
-           strncmp(sb+52, "ReIsEr2Fs",9)!=0)
+       if (strncmp((char*)sb+52, "ReIsErFs",8)!=0 &&
+           strncmp((char*)sb+52, "ReIsEr2Fs",9)!=0)
                return 0;
        fprintf(stderr, Name ": %s appears to contain a reiserfs file system\n",name);
        size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8;
@@ -210,25 +210,21 @@ int check_raid(int fd, char *name)
        void *super;
        struct mdinfo info;
        time_t crtime;
+       struct supertype *st = guess_super(fd);
 
-       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;
+       if (!st) return 0;
+       st->ss->load_super(st, fd, &super, name);
+       /* Looks like a raid array .. */
+       fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
+               name);
+       st->ss->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;
 }
 
-
 int ask(char *mesg)
 {
        char *add = "";
@@ -288,7 +284,7 @@ int is_standard(char *dev, int *nump)
        else if (strncmp(d, "/md", 3)==0)
                d += 3, type=-1; /* /dev/mdN */
        else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
-               type = -1; /* /dev/md/N */
+               d += 1, type=-1; /* /dev/md/N */
        else
                return 0;
        if (!*d)
@@ -390,6 +386,15 @@ unsigned long calc_csum(void *super, int bytes)
        for(i=0; i<bytes/4; i++)
                newcsum+= superc[i];
        csum = (newcsum& 0xffffffff) + (newcsum>>32);
+#ifdef __alpha__
+/* The in-kernel checksum calculation is always 16bit on 
+ * the alpha, though it is 32 bit on i386...
+ * I wonder what it is elsewhere... (it uses and API in
+ * a way that it shouldn't).
+ */
+       csum = (csum & 0xffff) + (csum >> 16);
+       csum = (csum & 0xffff) + (csum >> 16);
+#endif
        return csum;
 }
 
@@ -526,38 +531,64 @@ void put_md_name(char *name)
 
 
 
-struct superswitch *superlist[] = { &super0, NULL };
+struct superswitch *superlist[] = { &super0, &super1, NULL };
 
-struct superswitch *super_by_version(int vers)
+struct supertype *super_by_version(int vers, int minor)
 {
-       if (vers == 0) return &super0;
-       return NULL;
+       struct supertype *st = malloc(sizeof(*st));
+       if (!st) return st;
+       if (vers == 0) {
+               st->ss = &super0;
+               st->max_devs = MD_SB_DISKS;
+       }
+
+       if (vers == 1) {
+               st->ss = &super1;
+               st->max_devs = 384;
+       }
+       st->minor_version = minor;
+       return st;
 }
 
-struct superswitch *guess_super(int fd, char *dev)
+struct supertype *guess_super(int fd)
 {
        /* try each load_super to find the best match,
         * and return the best superswitch
         */
-       struct superswitch *best = NULL, *ss;
-       int bestrv = 0;
+       struct superswitch  *ss;
+       struct supertype *st;
+       unsigned long besttime = 0;
+       int bestsuper = -1;
+       
        void *sbp = NULL;
        int i;
 
+       st = malloc(sizeof(*st));
+       memset(st, 0, sizeof(*st));
        for (i=0 ; superlist[i]; i++) {
                int rv;
                ss = superlist[i];
-               rv = ss->load_super(fd, &sbp, NULL);
+               rv = ss->load_super(st, fd, &sbp, NULL);
                if (rv == 0) {
+                       struct mdinfo info;
+                       ss->getinfo_super(&info, sbp);
+                       if (bestsuper == -1 ||
+                           besttime < info.array.ctime) {
+                               bestsuper = i;
+                               besttime = info.array.ctime;
+                       }
+                       st->ss = NULL;
                        free(sbp);
-                       return ss;
                }
-               if (rv > bestrv) {
-                       bestrv  = rv;
-                       best = ss;
+       }
+       if (bestsuper != -1) {
+               int rv;
+               rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
+               if (rv == 0) {
+                       free(sbp);
+                       return st;
                }
        }
-       if (bestrv > 2) /* FIXME */
-               return best;
+       free(st);
        return NULL;
 }