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