summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2005-05-03 23:44:32 +0000
committerNeil Brown <neilb@suse.de>2005-05-03 23:44:32 +0000
commitf9ce90ba509d0b624cc38635861b9c27550fbefc (patch)
treede5576f6c939e0fd95f76030b4d273fdfc9f5945
parent4b1ac34b51a3783ab528b1af307156fab057b543 (diff)
downloadmdadm-f9ce90ba509d0b624cc38635861b9c27550fbefc.tar.gz
mdadm-f9ce90ba509d0b624cc38635861b9c27550fbefc.tar.xz
mdadm-f9ce90ba509d0b624cc38635861b9c27550fbefc.zip
Add a 'super-switch' so that different format superblocks can be used.
This includes: adding --metadata= option to choose metadata format adding metadata= word to config file. Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
-rw-r--r--Assemble.c36
-rw-r--r--Create.c8
-rw-r--r--Detail.c17
-rw-r--r--Examine.c22
-rw-r--r--Grow.c19
-rw-r--r--Kill.c17
-rw-r--r--Query.c11
-rw-r--r--ReadMe.c3
-rw-r--r--config.c11
-rw-r--r--mdadm.c43
-rw-r--r--mdadm.h42
-rw-r--r--super0.c62
-rw-r--r--util.c70
13 files changed, 262 insertions, 99 deletions
diff --git a/Assemble.c b/Assemble.c
index e762c69..3c09861 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -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);
diff --git a/Create.c b/Create.c
index 87a275e..15a7de8 100644
--- a/Create.c
+++ b/Create.c
@@ -31,7 +31,7 @@
#include "md_u.h"
#include "md_p.h"
-int Create(char *mddev, int mdfd,
+int Create(struct superswitch *ss, char *mddev, int mdfd,
int chunk, int level, int layout, unsigned long size, int raiddisks, int sparedisks,
int subdevs, mddev_dev_t devlist,
int runstop, int verbose, int force)
@@ -349,7 +349,7 @@ int Create(char *mddev, int mdfd,
return 1;
}
- init_super0(&super, &array);
+ ss->init_super(&super, &array);
for (pass=1; pass <=2 ; pass++) {
@@ -389,10 +389,10 @@ int Create(char *mddev, int mdfd,
}
switch(pass){
case 1:
- add_to_super0(super, &disk);
+ ss->add_to_super(super, &disk);
break;
case 2:
- write_init_super0(super, &disk, dv->devname);
+ ss->write_init_super(super, &disk, dv->devname);
if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
diff --git a/Detail.c b/Detail.c
index 59b091f..2f3fc7f 100644
--- a/Detail.c
+++ b/Detail.c
@@ -50,6 +50,7 @@ int Detail(char *dev, int brief, int test)
int is_26 = get_linux_version() >= 2006000;
int is_rebuilding = 0;
int failed = 0;
+ struct superswitch *ss = NULL;
void *super = NULL;
int rv = test ? 4 : 1;
@@ -82,6 +83,8 @@ int Detail(char *dev, int brief, int test)
close(fd);
return rv;
}
+ ss = super_by_version(array.major_version);
+
if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
stb.st_rdev = 0;
rv = 0;
@@ -103,10 +106,10 @@ int Detail(char *dev, int brief, int test)
* to get more info
*/
int fd2 = open(dv, O_RDONLY);
- if (fd2 >=0 &&
- load_super0(fd2, &super, NULL) == 0) {
+ if (fd2 >=0 && ss &&
+ ss->load_super(fd2, &super, NULL) == 0) {
struct mdinfo info;
- getinfo_super0(&info, super);
+ ss->getinfo_super(&info, super);
if (info.array.ctime != array.ctime ||
info.array.level != array.level) {
free(super);
@@ -202,8 +205,8 @@ int Detail(char *dev, int brief, int test)
}
free_mdstat(ms);
- if (super)
- detail_super0(super);
+ if (super && ss)
+ ss->detail_super(super);
printf(" Number Major Minor RaidDevice State\n");
}
@@ -275,8 +278,8 @@ int Detail(char *dev, int brief, int test)
if (!brief) printf("\n");
}
if (spares && brief) printf(" spares=%d", spares);
- if (super && brief)
- brief_detail_super0(super);
+ if (super && brief && ss)
+ ss->brief_detail_super(super);
if (brief && devices) printf("\n devices=%s", devices);
if (brief) printf("\n");
diff --git a/Examine.c b/Examine.c
index cd79583..8081b66 100644
--- a/Examine.c
+++ b/Examine.c
@@ -60,6 +60,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
struct array {
void *super;
+ struct superswitch *ss;
struct mdinfo info;
void *devs;
struct array *next;
@@ -67,6 +68,8 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
} *arrays = NULL;
for (; devlist ; devlist=devlist->next) {
+ struct superswitch *ss;
+
fd = open(devlist->devname, O_RDONLY);
if (fd < 0) {
if (!scan)
@@ -75,7 +78,11 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
err = 1;
}
else {
- err = load_super0(fd, &super, (brief||scan)?NULL:devlist->devname);
+ ss = guess_super(fd, devlist->devname);
+ if (ss)
+ err = ss->load_super(fd, &super, (brief||scan)?NULL:devlist->devname);
+ else
+ err = 1;
close(fd);
}
if (err)
@@ -83,13 +90,13 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
if (err) rv =1;
if (SparcAdjust)
- update_super0(NULL, super, "sparc2.2", devlist->devname, 0);
+ ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0);
/* Ok, its good enough to try, though the checksum could be wrong */
if (brief) {
struct array *ap;
char *d;
for (ap=arrays; ap; ap=ap->next) {
- if (compare_super0(&ap->super, super)==0)
+ if (ss == ap->ss && ss->compare_super(&ap->super, super)==0)
break;
}
if (!ap) {
@@ -98,10 +105,11 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
ap->devs = dl_head();
ap->next = arrays;
ap->spares = 0;
+ ap->ss = ss;
arrays = ap;
- getinfo_super0(&ap->info, super);
+ ss->getinfo_super(&ap->info, super);
} else {
- getinfo_super0(&ap->info, super);
+ ss->getinfo_super(&ap->info, super);
free(super);
}
if (!(ap->info.disk.state & MD_DISK_SYNC))
@@ -110,7 +118,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
dl_add(ap->devs, d);
} else {
printf("%s:\n",devlist->devname);
- examine_super0(super);
+ ss->examine_super(super);
free(super);
}
}
@@ -119,7 +127,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
for (ap=arrays; ap; ap=ap->next) {
char sep='=';
char *d;
- brief_examine_super0(ap->super);
+ ap->ss->brief_examine_super(ap->super);
if (ap->spares) printf(" spares=%d", ap->spares);
printf(" devices");
for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
diff --git a/Grow.c b/Grow.c
index 8de28d4..ec2eb55 100644
--- a/Grow.c
+++ b/Grow.c
@@ -51,6 +51,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
struct stat stb;
int nfd, fd2;
int d, nd;
+ struct superswitch *ss = NULL;
if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) {
@@ -58,6 +59,12 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
return 1;
}
+ ss = super_by_version(info.array.major_version);
+ if (!ss) {
+ fprintf(stderr, Name ": cannot handle arrays with superblock version %d\n", info.array.major_version);
+ return 1;
+ }
+
if (info.array.level != -1) {
fprintf(stderr, Name ": can only add devices to linear arrays\n");
return 1;
@@ -98,7 +105,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
}
if (super) free(super);
super= NULL;
- if (load_super0(fd2, &super, NULL)) {
+ if (ss->load_super(fd2, &super, NULL)) {
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
close(fd2);
return 1;
@@ -114,9 +121,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
info.disk.minor = minor(stb.st_rdev);
info.disk.raid_disk = d;
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
- update_super0(&info, super, "grow", newdev, 0);
+ ss->update_super(&info, super, "grow", newdev, 0);
- if (store_super0(nfd, super)) {
+ if (ss->store_super(nfd, super)) {
fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
close(nfd);
return 1;
@@ -158,7 +165,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
fprintf(stderr, Name ": cannot open device file %s\n", dv);
return 1;
}
- if (load_super0(fd2, &super, NULL)) {
+ if (ss->load_super(fd2, &super, NULL)) {
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
close(fd);
return 1;
@@ -172,9 +179,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
info.disk.minor = minor(stb.st_rdev);
info.disk.raid_disk = nd;
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
- update_super0(&info, super, "grow", dv, 0);
+ ss->update_super(&info, super, "grow", dv, 0);
- if (store_super0(fd2, super)) {
+ if (ss->store_super(fd2, super)) {
fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
close(fd2);
return 1;
diff --git a/Kill.c b/Kill.c
index fbda686..b20c28e 100644
--- a/Kill.c
+++ b/Kill.c
@@ -43,19 +43,28 @@ int Kill(char *dev, int force)
void *super;
int fd, rv = 0;
+ struct superswitch *ss;
fd = open(dev, O_RDWR|O_EXCL);
if (fd < 0) {
fprintf(stderr, Name ": Couldn't open %s for write - not zeroing\n",
dev);
return 1;
- }
- rv = load_super0(fd, &super, dev);
+ }
+ ss = guess_super(fd, dev);
+ if (ss == NULL) {
+ fprintf(stderr, Name ": Unrecognised md component device - %s\n", dev);
+ return 1;
+ }
+ rv = ss->load_super(fd, &super, dev);
if (force && rv >= 2)
rv = 0; /* ignore bad data in superblock */
if (rv== 0 || (force && rv >= 2)) {
- memset(&super, 0, sizeof(super));
- if (store_super0(fd, super)) {
+ mdu_array_info_t info;
+ info.major_version = -1; /* zero superblock */
+ free(super);
+ ss->init_super(&super, &info);
+ if (ss->store_super(fd, super)) {
fprintf(stderr, Name ": Could not zero superblock on %s\n",
dev);
rv = 1;
diff --git a/Query.c b/Query.c
index 71aafd8..88df321 100644
--- a/Query.c
+++ b/Query.c
@@ -44,6 +44,7 @@ int Query(char *dev)
struct mdinfo info;
mdu_array_info_t array;
void *super;
+ struct superswitch *ss = NULL;
unsigned long long larray_size;
unsigned long array_size;
@@ -94,12 +95,16 @@ int Query(char *dev)
array.raid_disks,
array.spare_disks, array.spare_disks==1?"":"s");
}
- superror = load_super0(fd, &super, dev);
- superrno = errno;
+ ss = guess_super(fd, dev);
+ if (ss) {
+ superror = ss->load_super(fd, &super, dev);
+ superrno = errno;
+ } else
+ superror = -1;
close(fd);
if (superror == 0) {
/* array might be active... */
- getinfo_super0(&info, super);
+ ss->getinfo_super(&info, super);
mddev = get_md_name(info.array.md_minor);
disc.number = info.disk.number;
activity = "undetected";
diff --git a/ReadMe.c b/ReadMe.c
index 00283e9..367bc0b 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -91,7 +91,7 @@ char Version[] = Name " - v1.11.0 - 11 April 2005\n";
* At the time if writing, there is only minimal support.
*/
-char short_options[]="-ABCDEFGQhVvbc:i:l:p:m:n:x:u:c:d:z:U:sa::rfRSow1t";
+char short_options[]="-ABCDEFGQhVvbc:i:l:p:m:n:x:u:c:d:z:U:sa::rfRSow1te:";
struct option long_options[] = {
{"manage", 0, 0, '@'},
{"misc", 0, 0, '#'},
@@ -127,6 +127,7 @@ struct option long_options[] = {
{"size", 1, 0, 'z'},
{"auto", 2, 0, 'a'}, /* also for --assemble */
{"assume-clean",0,0, 3 },
+ {"metadata", 1, 0, 'e'}, /* superblock format */
/* For assemble */
{"uuid", 1, 0, 'u'},
diff --git a/config.c b/config.c
index 0aac1a0..f3a749c 100644
--- a/config.c
+++ b/config.c
@@ -328,6 +328,17 @@ void arrayline(char *line)
} else if (strncasecmp(w, "spares=", 7) == 0 ) {
/* for warning if not all spares present */
mis.spare_disks = atoi(w+7);
+ } else if (strncasecmp(w, "metadata=", 9) == 0) {
+ /* style of metadata on the devices. */
+ int i;
+
+ for(i=0; superlist[i]; i++)
+ if (superlist[i]->match_metadata_desc(w+9)) {
+ mis.ss = superlist[i];
+ break;
+ }
+ if (!mis.ss)
+ fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
} else if (strncasecmp(w, "auto=", 5) == 0 ) {
/* whether to create device special files as needed */
if (strcasecmp(w+5, "no")==0)
diff --git a/mdadm.c b/mdadm.c
index daf2412..b738fad 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -32,7 +32,6 @@
#include <ctype.h>
-
int main(int argc, char *argv[])
{
int mode = 0;
@@ -41,6 +40,7 @@ int main(int argc, char *argv[])
char *help_text;
char *c;
int rv;
+ int i;
int chunk = 0;
int size = -1;
@@ -81,6 +81,7 @@ int main(int argc, char *argv[])
int daemonise = 0;
char *pidfile = NULL;
int oneshot = 0;
+ struct superswitch *ss = NULL;
int copies;
@@ -273,6 +274,24 @@ int main(int argc, char *argv[])
}
continue;
+ case O(CREATE,'e'):
+ case O(ASSEMBLE,'e'):
+ case O(MISC,'e'): /* set metadata (superblock) information */
+ if (ss) {
+ fprintf(stderr, Name ": metadata information already given\n");
+ exit(2);
+ }
+ for(i=0; superlist[i]; i++)
+ if (superlist[i]->match_metadata_desc(optarg)) {
+ ss = superlist[i];
+ break;
+ }
+ if (!ss) {
+ fprintf(stderr, Name ": unrecognised metadata identifier: %s\n", optarg);
+ exit(2);
+ }
+ continue;
+
case O(GROW,'z'):
case O(CREATE,'z'): /* size */
if (size >= 0) {
@@ -736,14 +755,14 @@ int main(int argc, char *argv[])
if (mdfd < 0)
rv |= 1;
else {
- rv |= Assemble(devlist->devname, mdfd, array_ident, configfile,
+ rv |= Assemble(ss, devlist->devname, mdfd, array_ident, configfile,
NULL,
readonly, runstop, update, verbose, force);
close(mdfd);
}
}
} else if (!scan)
- rv = Assemble(devlist->devname, mdfd, &ident, configfile,
+ rv = Assemble(ss, devlist->devname, mdfd, &ident, configfile,
devlist->next,
readonly, runstop, update, verbose, force);
else if (devs_found>0) {
@@ -764,7 +783,7 @@ int main(int argc, char *argv[])
rv |= 1;
continue;
}
- rv |= Assemble(dv->devname, mdfd, array_ident, configfile,
+ rv |= Assemble(ss, dv->devname, mdfd, array_ident, configfile,
NULL,
readonly, runstop, update, verbose, force);
close(mdfd);
@@ -786,7 +805,7 @@ int main(int argc, char *argv[])
/* already assembled, skip */
;
else
- rv |= Assemble(array_list->devname, mdfd,
+ rv |= Assemble(ss, array_list->devname, mdfd,
array_list, configfile,
NULL,
readonly, runstop, NULL, verbose, force);
@@ -798,7 +817,19 @@ int main(int argc, char *argv[])
rv = Build(devlist->devname, mdfd, chunk, level, layout, raiddisks, devlist->next, assume_clean);
break;
case CREATE:
- rv = Create(devlist->devname, mdfd, chunk, level, layout, size<0 ? 0 : size,
+ if (ss == NULL) {
+ for(i=0; superlist[i]; i++)
+ if (superlist[i]->match_metadata_desc("default")) {
+ ss = superlist[i];
+ break;
+ }
+ }
+ if (!ss) {
+ fprintf(stderr, Name ": internal error - no default metadata style\n");
+ exit(2);
+ }
+
+ rv = Create(ss, devlist->devname, mdfd, chunk, level, layout, size<0 ? 0 : size,
raiddisks, sparedisks,
devs_found-1, devlist->next, runstop, verbose, force);
break;
diff --git a/mdadm.h b/mdadm.h
index 6638a34..491d907 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -116,6 +116,7 @@ typedef struct mddev_ident_s {
int level;
unsigned int raid_disks;
unsigned int spare_disks;
+ struct superswitch *ss;
int autof; /* 1 for normal, 2 for partitioned */
char *spare_group;
@@ -163,6 +164,28 @@ extern mapping_t r5layout[], pers[], modes[], faultylayout[];
extern char *map_dev(int major, int minor);
+extern struct superswitch {
+ void (*examine_super)(void *sbv);
+ void (*brief_examine_super)(void *sbv);
+ void (*detail_super)(void *sbv);
+ void (*brief_detail_super)(void *sbv);
+ void (*uuid_from_super)(int uuid[4], void *sbv);
+ void (*getinfo_super)(struct mdinfo *info, void *sbv);
+ int (*update_super)(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose);
+ __u64 (*event_super)(void *sbv);
+ void (*init_super)(void **sbp, mdu_array_info_t *info);
+ void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
+ int (*store_super)(int fd, void *sbv);
+ int (*write_init_super)(void *sbv, mdu_disk_info_t *dinfo, char *devname);
+ int (*compare_super)(void **firstp, void *secondv);
+ int (*load_super)(int fd, void **sbp, char *devname);
+ int (*match_metadata_desc)(char *arg);
+} super0, *superlist[];
+
+extern struct superswitch *super_by_version(int vers);
+extern struct superswitch *guess_super(int fd, char *dev);
+
+
extern int Manage_ro(char *devname, int fd, int readonly);
extern int Manage_runstop(char *devname, int fd, int runstop);
extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
@@ -172,7 +195,7 @@ extern int Manage_subdevs(char *devname, int fd,
extern int Grow_Add_device(char *devname, int fd, char *newdev);
-extern int Assemble(char *mddev, int mdfd,
+extern int Assemble(struct superswitch *ss, char *mddev, int mdfd,
mddev_ident_t ident,
char *conffile,
mddev_dev_t devlist,
@@ -185,7 +208,7 @@ extern int Build(char *mddev, int mdfd, int chunk, int level, int layout,
mddev_dev_t devlist, int assume_clean);
-extern int Create(char *mddev, int mdfd,
+extern int Create(struct superswitch *ss, char *mddev, int mdfd,
int chunk, int level, int layout, unsigned long size, int raiddisks, int sparedisks,
int subdevs, mddev_dev_t devlist,
int runstop, int verbose, int force);
@@ -262,18 +285,3 @@ extern int open_mddev(char *dev, int autof);
#define ModeMask 0x1f
#define ModeShift 5
-
-extern void examine_super0(void *sbv);
-extern void brief_examine_super0(void *sbv);
-extern void detail_super0(void *sbv);
-extern void brief_detail_super0(void *sbv);
-extern void getinfo_super0(struct mdinfo *info, void *sbv);
-extern int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose);
-extern __u64 event_super0(void *sbv);
-extern void uuid_from_super0(int uuid[4], void * sbv);
-extern void init_super0(void **sbv, mdu_array_info_t *info);
-extern void add_to_super0(void *sbp, mdu_disk_info_t *dinfo);
-extern int store_super0(int fd, mdp_super_t *super);
-extern int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname);
-extern int load_super0(int fd, void **super, char *devname);
-extern int compare_super0(void **first, void *second);
diff --git a/super0.c b/super0.c
index a65d1e1..4cd2cc3 100644
--- a/super0.c
+++ b/super0.c
@@ -51,7 +51,7 @@ static unsigned long calc_sb0_csum(mdp_super_t *super)
return newcsum;
}
-void examine_super0(void *sbv)
+static void examine_super0(void *sbv)
{
mdp_super_t *sb = sbv;
time_t atime;
@@ -129,7 +129,7 @@ void examine_super0(void *sbv)
}
}
-void brief_examine_super0(void *sbv)
+static void brief_examine_super0(void *sbv)
{
mdp_super_t *sb = sbv;
char *c=map_num(pers, sb->level);
@@ -145,7 +145,7 @@ void brief_examine_super0(void *sbv)
printf("\n");
}
-void detail_super0(void *sbv)
+static void detail_super0(void *sbv)
{
mdp_super_t *sb = sbv;
printf(" UUID : ");
@@ -157,7 +157,7 @@ void detail_super0(void *sbv)
printf("\n Events : %d.%d\n\n", sb->events_hi, sb->events_lo);
}
-void brief_detail_super0(void *sbv)
+static void brief_detail_super0(void *sbv)
{
mdp_super_t *sb = sbv;
printf(" UUID=");
@@ -168,7 +168,7 @@ void brief_detail_super0(void *sbv)
printf("%08x", sb->set_uuid0);
}
-void uuid_from_super0(int uuid[4], void * sbv)
+static void uuid_from_super0(int uuid[4], void * sbv)
{
mdp_super_t *super = sbv;
uuid[0] = super->set_uuid0;
@@ -183,7 +183,7 @@ void uuid_from_super0(int uuid[4], void * sbv)
}
}
-void getinfo_super0(struct mdinfo *info, void *sbv)
+static void getinfo_super0(struct mdinfo *info, void *sbv)
{
mdp_super_t *sb = sbv;
int working = 0;
@@ -216,7 +216,7 @@ void getinfo_super0(struct mdinfo *info, void *sbv)
}
-int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
+static int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
{
int rv = 0;
mdp_super_t *sb = sbv;
@@ -314,7 +314,7 @@ int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, i
return rv;
}
-__u64 event_super0(void *sbv)
+static __u64 event_super0(void *sbv)
{
mdp_super_t *sb = sbv;
return md_event(sb);
@@ -322,11 +322,16 @@ __u64 event_super0(void *sbv)
-void init_super0(void **sbp, mdu_array_info_t *info)
+static void init_super0(void **sbp, mdu_array_info_t *info)
{
mdp_super_t *sb = malloc(MD_SB_BYTES);
memset(sb, 0, MD_SB_BYTES);
+ if (info->major_version == -1) {
+ /* zeroing the superblock */
+ return;
+ }
+
sb->md_magic = MD_SB_MAGIC;
sb->major_version = 0;
sb->minor_version = 90;
@@ -359,7 +364,7 @@ void init_super0(void **sbp, mdu_array_info_t *info)
}
/* Add a device to the superblock being created */
-void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
+static void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
{
mdp_super_t *sb = sbv;
mdp_disk_t *dk = &sb->disks[dinfo->number];
@@ -371,11 +376,12 @@ void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
dk->state = dinfo->state;
}
-int store_super0(int fd, mdp_super_t *super)
+static int store_super0(int fd, void *sbv)
{
unsigned long size;
unsigned long long dsize;
unsigned long long offset;
+ mdp_super_t *super = sbv;
#ifdef BLKGETSIZE64
if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
@@ -403,7 +409,7 @@ int store_super0(int fd, mdp_super_t *super)
return 0;
}
-int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname)
+static int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname)
{
mdp_super_t *sb = sbv;
int fd = open(devname, O_RDWR, O_EXCL);
@@ -423,7 +429,7 @@ int write_init_super0(void *sbv, mdu_disk_info_t *dinfo, char *devname)
return rv;
}
-int compare_super0(void **firstp, void *secondv)
+static int compare_super0(void **firstp, void *secondv)
{
/*
* return:
@@ -463,7 +469,7 @@ int compare_super0(void **firstp, void *secondv)
}
-int load_super0(int fd, void **sbp, char *devname)
+static int load_super0(int fd, void **sbp, char *devname)
{
/* try to read in the superblock
* Return:
@@ -537,3 +543,31 @@ int load_super0(int fd, void **sbp, char *devname)
*sbp = super;
return 0;
}
+
+static int match_metadata_desc0(char *arg)
+{
+ if (strcmp(arg, "0") == 0 ||
+ strcmp(arg, "0.90") == 0 ||
+ strcmp(arg, "default") == 0
+ )
+ return 1;
+ return 0;
+}
+
+struct superswitch super0 = {
+ .examine_super = examine_super0,
+ .brief_examine_super = brief_examine_super0,
+ .detail_super = detail_super0,
+ .brief_detail_super = brief_detail_super0,
+ .uuid_from_super = uuid_from_super0,
+ .getinfo_super = getinfo_super0,
+ .update_super = update_super0,
+ .event_super = event_super0,
+ .init_super = init_super0,
+ .add_to_super = add_to_super0,
+ .store_super = store_super0,
+ .write_init_super = write_init_super0,
+ .compare_super = compare_super0,
+ .load_super = load_super0,
+ .match_metadata_desc = match_metadata_desc0,
+};
diff --git a/util.c b/util.c
index e9bce2a..f243d88 100644
--- a/util.c
+++ b/util.c
@@ -205,26 +205,27 @@ int check_reiser(int fd, char *name)
return 1;
}
-int load_super(int fd, void **sbp, int vers)
-{
- return load_super0(fd, sbp, NULL);
-}
int check_raid(int fd, char *name)
{
void *super;
struct mdinfo info;
time_t crtime;
- if (load_super(fd, &super, -1))
- return 0;
- /* Looks like a raid array .. */
- fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
- name);
- getinfo_super0(&info, super);
- free(super);
- crtime = info.array.ctime;
- fprintf(stderr, " level=%d devices=%d ctime=%s",
- info.array.level, info.array.raid_disks, ctime(&crtime));
- return 1;
+
+ int i;
+ for (i=0; superlist[i]; i++) {
+ if (superlist[i]->load_super(fd, &super, name))
+ continue;
+ /* Looks like a raid array .. */
+ fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
+ name);
+ superlist[i]->getinfo_super(&info, super);
+ free(super);
+ crtime = info.array.ctime;
+ fprintf(stderr, " level=%d devices=%d ctime=%s",
+ info.array.level, info.array.raid_disks, ctime(&crtime));
+ return 1;
+ }
+ return 0;
}
@@ -521,3 +522,42 @@ void put_md_name(char *name)
if (strncmp(name, "/dev/.tmp.md", 12)==0)
unlink(name);
}
+
+
+
+
+struct superswitch *superlist[] = { &super0, NULL };
+
+struct superswitch *super_by_version(int vers)
+{
+ if (vers == 0) return &super0;
+ return NULL;
+}
+
+struct superswitch *guess_super(int fd, char *dev)
+{
+ /* try each load_super to find the best match,
+ * and return the best superswitch
+ */
+ struct superswitch *best = NULL, *ss;
+ int bestrv = 0;
+ void *sbp = NULL;
+ int i;
+
+ for (i=0 ; superlist[i]; i++) {
+ int rv;
+ ss = superlist[i];
+ rv = ss->load_super(fd, &sbp, NULL);
+ if (rv == 0) {
+ free(sbp);
+ return ss;
+ }
+ if (rv > bestrv) {
+ bestrv = rv;
+ best = ss;
+ }
+ }
+ if (bestrv > 2) /* FIXME */
+ return best;
+ return NULL;
+}