X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=util.c;h=010764ea0661b5a8c0a7fbaa326e29fa9e9621da;hp=e9bce2a177f61f8d52c06caec17cc6f2fc770543;hb=570c05424705e5f9740567b3683a8d45b7a765f6;hpb=4b1ac34b51a3783ab528b1af307156fab057b543 diff --git a/util.c b/util.c index e9bce2a1..010764ea 100644 --- a/util.c +++ b/util.c @@ -205,21 +205,19 @@ int check_reiser(int fd, char *name) return 1; } -int load_super(int fd, void **sbp, int vers) -{ - return load_super0(fd, sbp, NULL); -} int check_raid(int fd, char *name) { void *super; struct mdinfo info; time_t crtime; - if (load_super(fd, &super, -1)) - return 0; + struct supertype *st = guess_super(fd); + + 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); - getinfo_super0(&info, super); + st->ss->getinfo_super(&info, super); free(super); crtime = info.array.ctime; fprintf(stderr, " level=%d devices=%d ctime=%s", @@ -227,7 +225,6 @@ int check_raid(int fd, char *name) return 1; } - int ask(char *mesg) { char *add = ""; @@ -389,6 +386,15 @@ unsigned long calc_csum(void *super, int bytes) for(i=0; i>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; } @@ -521,3 +527,64 @@ void put_md_name(char *name) if (strncmp(name, "/dev/.tmp.md", 12)==0) unlink(name); } + + + + +struct superswitch *superlist[] = { &super0, &super1, NULL }; + +struct supertype *super_by_version(int vers, int minor) +{ + struct supertype *st = malloc(sizeof(*st)); + if (!st) return st; + if (vers == 0) + st->ss = &super0; + + if (vers == 1) + st->ss = &super1; + st->minor_version = minor; + return st; +} + +struct supertype *guess_super(int fd) +{ + /* try each load_super to find the best match, + * and return the best superswitch + */ + 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(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); + } + } + if (bestsuper != -1) { + int rv; + rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL); + if (rv == 0) { + free(sbp); + return st; + } + } + free(st); + return NULL; +}