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>
This commit is contained in:
parent
4b1ac34b51
commit
f9ce90ba50
36
Assemble.c
36
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);
|
||||
|
|
8
Create.c
8
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",
|
||||
|
|
17
Detail.c
17
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");
|
||||
|
|
22
Examine.c
22
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)) {
|
||||
|
|
19
Grow.c
19
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;
|
||||
|
|
17
Kill.c
17
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;
|
||||
|
|
11
Query.c
11
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";
|
||||
|
|
3
ReadMe.c
3
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'},
|
||||
|
|
11
config.c
11
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)
|
||||
|
|
43
mdadm.c
43
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;
|
||||
|
|
42
mdadm.h
42
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);
|
||||
|
|
62
super0.c
62
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,
|
||||
};
|
||||
|
|
70
util.c
70
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue