Separate sueprblock handling into separate file
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
This commit is contained in:
parent
e5811618d1
commit
4b1ac34b51
241
Assemble.c
241
Assemble.c
|
@ -28,8 +28,6 @@
|
|||
*/
|
||||
|
||||
#include "mdadm.h"
|
||||
#include "md_u.h"
|
||||
#include "md_p.h"
|
||||
|
||||
int Assemble(char *mddev, int mdfd,
|
||||
mddev_ident_t ident, char *conffile,
|
||||
|
@ -52,11 +50,11 @@ int Assemble(char *mddev, int mdfd,
|
|||
* Much of the work of Assemble is in finding and/or
|
||||
* checking the disks to make sure they look right.
|
||||
*
|
||||
* If mddev is not set, then scan must be and we
|
||||
* If mddev is not set, then scan must be set and we
|
||||
* read through the config file for dev+uuid mapping
|
||||
* We recurse, setting mddev, for each device that
|
||||
* - isn't running
|
||||
* - has a valid uuid (or any uuid if !uuidset
|
||||
* - has a valid uuid (or any uuid if !uuidset)
|
||||
*
|
||||
* If mddev is set, we try to determine state of md.
|
||||
* check version - must be at least 0.90.0
|
||||
|
@ -74,9 +72,9 @@ int Assemble(char *mddev, int mdfd,
|
|||
* Check superblock - discard if bad
|
||||
* Check uuid (set if we don't have one) - discard if no match
|
||||
* Check superblock similarity if we have a superblock - discard if different
|
||||
* Record events, devicenum, utime
|
||||
* Record events, devicenum
|
||||
* This should give us a list of devices for the array
|
||||
* We should collect the most recent event and utime numbers
|
||||
* We should collect the most recent event number
|
||||
*
|
||||
* Count disks with recent enough event count
|
||||
* While force && !enough disks
|
||||
|
@ -94,14 +92,12 @@ int Assemble(char *mddev, int mdfd,
|
|||
*/
|
||||
int old_linux = 0;
|
||||
int vers;
|
||||
mdu_array_info_t array;
|
||||
mdp_super_t first_super, super;
|
||||
void *first_super = NULL, *super = NULL;
|
||||
struct {
|
||||
char *devname;
|
||||
unsigned int major, minor;
|
||||
unsigned int oldmajor, oldminor;
|
||||
long long events;
|
||||
time_t utime;
|
||||
int uptodate;
|
||||
int state;
|
||||
int raid_disk;
|
||||
|
@ -119,6 +115,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
int start_partial_ok = force || devlist==NULL;
|
||||
unsigned int num_devs;
|
||||
mddev_dev_t tmpdev;
|
||||
struct mdinfo info;
|
||||
|
||||
vers = md_get_version(mdfd);
|
||||
if (vers <= 0) {
|
||||
|
@ -133,7 +130,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
if (get_linux_version() < 2004000)
|
||||
old_linux = 1;
|
||||
|
||||
if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) {
|
||||
if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) {
|
||||
fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
|
||||
mddev);
|
||||
return 1;
|
||||
|
@ -165,12 +162,8 @@ int Assemble(char *mddev, int mdfd,
|
|||
num_devs++;
|
||||
tmpdev = tmpdev->next;
|
||||
}
|
||||
best = malloc(num_devs * sizeof(*best));
|
||||
devices = malloc(num_devs * sizeof(*devices));
|
||||
|
||||
first_super.md_magic = 0;
|
||||
for (i=0; i<num_devs; i++)
|
||||
best[i] = -1;
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": looking for devices for %s\n",
|
||||
|
@ -178,10 +171,8 @@ int Assemble(char *mddev, int mdfd,
|
|||
|
||||
while ( devlist) {
|
||||
char *devname;
|
||||
int this_uuid[4];
|
||||
int dfd;
|
||||
struct stat stb;
|
||||
int havesuper=0;
|
||||
|
||||
devname = devlist->devname;
|
||||
devlist = devlist->next;
|
||||
|
@ -192,6 +183,11 @@ int Assemble(char *mddev, int mdfd,
|
|||
fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (super) {
|
||||
free(super);
|
||||
super = NULL;
|
||||
}
|
||||
|
||||
dfd = open(devname, O_RDONLY|O_EXCL, 0);
|
||||
if (dfd < 0) {
|
||||
|
@ -207,40 +203,39 @@ int Assemble(char *mddev, int mdfd,
|
|||
fprintf(stderr, Name ": %s is not a block device.\n",
|
||||
devname);
|
||||
close(dfd);
|
||||
} else if (load_super(dfd, &super)) {
|
||||
} else if (load_super0(dfd, &super, NULL)) {
|
||||
if (inargv || verbose)
|
||||
fprintf( stderr, Name ": no RAID superblock on %s\n",
|
||||
devname);
|
||||
close(dfd);
|
||||
} else {
|
||||
havesuper =1;
|
||||
uuid_from_super(this_uuid, &super);
|
||||
getinfo_super0(&info, super);
|
||||
close(dfd);
|
||||
}
|
||||
|
||||
if (ident->uuid_set &&
|
||||
(!havesuper || same_uuid(this_uuid, ident->uuid)==0)) {
|
||||
(!super || same_uuid(info.uuid, ident->uuid)==0)) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, Name ": %s has wrong uuid.\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
if (ident->super_minor != UnSet &&
|
||||
(!havesuper || ident->super_minor != super.md_minor)) {
|
||||
(!super || ident->super_minor != info.array.md_minor)) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, Name ": %s has wrong super-minor.\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
if (ident->level != UnSet &&
|
||||
(!havesuper|| ident->level != (int)super.level)) {
|
||||
(!super|| ident->level != info.array.level)) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, Name ": %s has wrong raid level.\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
if (ident->raid_disks != UnSet &&
|
||||
(!havesuper || ident->raid_disks!= super.raid_disks)) {
|
||||
(!super || ident->raid_disks!= info.array.raid_disks)) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, Name ": %s requires wrong number of drives.\n",
|
||||
devname);
|
||||
|
@ -252,85 +247,34 @@ int Assemble(char *mddev, int mdfd,
|
|||
* then we cannot continue
|
||||
*/
|
||||
|
||||
if (!havesuper) {
|
||||
if (!super) {
|
||||
fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
|
||||
devname);
|
||||
free(first_super);
|
||||
return 1;
|
||||
}
|
||||
if (compare_super(&first_super, &super)) {
|
||||
if (compare_super0(&first_super, super)) {
|
||||
fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
|
||||
devname);
|
||||
free(super);
|
||||
free(first_super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* this is needed until we get a more relaxed super block format */
|
||||
if (devcnt >= MD_SB_DISKS) {
|
||||
fprintf(stderr, Name ": ouch - too many devices appear to be in this array. Ignoring %s\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* looks like a good enough match to update the super block if needed */
|
||||
if (update) {
|
||||
if (strcmp(update, "sparc2.2")==0 ) {
|
||||
/* 2.2 sparc put the events in the wrong place
|
||||
* So we copy the tail of the superblock
|
||||
* up 4 bytes before continuing
|
||||
*/
|
||||
__u32 *sb32 = (__u32*)&super;
|
||||
memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
|
||||
sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
|
||||
(MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
|
||||
fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
|
||||
devname);
|
||||
}
|
||||
if (strcmp(update, "super-minor") ==0) {
|
||||
struct stat stb2;
|
||||
fstat(mdfd, &stb2);
|
||||
super.md_minor = minor(stb2.st_rdev);
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
|
||||
devname, super.md_minor);
|
||||
}
|
||||
if (strcmp(update, "summaries") == 0) {
|
||||
/* set nr_disks, active_disks, working_disks,
|
||||
* failed_disks, spare_disks based on disks[]
|
||||
* array in superblock.
|
||||
* Also make sure extra slots aren't 'failed'
|
||||
*/
|
||||
super.nr_disks = super.active_disks =
|
||||
super.working_disks = super.failed_disks =
|
||||
super.spare_disks = 0;
|
||||
for (i=0; i < MD_SB_DISKS ; i++)
|
||||
if (super.disks[i].major ||
|
||||
super.disks[i].minor) {
|
||||
int state = super.disks[i].state;
|
||||
if (state & (1<<MD_DISK_REMOVED))
|
||||
continue;
|
||||
super.nr_disks++;
|
||||
if (state & (1<<MD_DISK_ACTIVE))
|
||||
super.active_disks++;
|
||||
if (state & (1<<MD_DISK_FAULTY))
|
||||
super.failed_disks++;
|
||||
else
|
||||
super.working_disks++;
|
||||
if (state == 0)
|
||||
super.spare_disks++;
|
||||
} else if (i >= super.raid_disks && super.disks[i].number == 0)
|
||||
super.disks[i].state = 0;
|
||||
}
|
||||
if (strcmp(update, "resync") == 0) {
|
||||
/* make sure resync happens */
|
||||
super.state &= ~(1<<MD_SB_CLEAN);
|
||||
super.recovery_cp = 0;
|
||||
}
|
||||
super.sb_csum = calc_sb_csum(&super);
|
||||
/* prepare useful information in info structures */
|
||||
struct stat stb2;
|
||||
fstat(mdfd, &stb2);
|
||||
info.array.md_minor = minor(stb2.st_rdev);
|
||||
|
||||
update_super0(&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_super(dfd, &super))
|
||||
else if (store_super0(dfd, super))
|
||||
fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
|
||||
devname);
|
||||
if (dfd >= 0)
|
||||
|
@ -339,23 +283,22 @@ int Assemble(char *mddev, int mdfd,
|
|||
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
|
||||
devname, mddev, super.this_disk.raid_disk);
|
||||
devname, mddev, info.disk.raid_disk);
|
||||
devices[devcnt].devname = devname;
|
||||
devices[devcnt].major = major(stb.st_rdev);
|
||||
devices[devcnt].minor = minor(stb.st_rdev);
|
||||
devices[devcnt].oldmajor = super.this_disk.major;
|
||||
devices[devcnt].oldminor = super.this_disk.minor;
|
||||
devices[devcnt].events = md_event(&super);
|
||||
devices[devcnt].utime = super.utime;
|
||||
devices[devcnt].raid_disk = super.this_disk.raid_disk;
|
||||
devices[devcnt].oldmajor = info.disk.major;
|
||||
devices[devcnt].oldminor = info.disk.minor;
|
||||
devices[devcnt].events = info.events;
|
||||
devices[devcnt].raid_disk = info.disk.raid_disk;
|
||||
devices[devcnt].uptodate = 0;
|
||||
devices[devcnt].state = super.this_disk.state;
|
||||
devices[devcnt].state = info.disk.state;
|
||||
if (most_recent < devcnt) {
|
||||
if (devices[devcnt].events
|
||||
> devices[most_recent].events)
|
||||
most_recent = devcnt;
|
||||
}
|
||||
if ((int)super.level == -4)
|
||||
if (info.array.level == -4)
|
||||
/* with multipath, the raid_disk from the superblock is meaningless */
|
||||
i = devcnt;
|
||||
else
|
||||
|
@ -381,11 +324,19 @@ int Assemble(char *mddev, int mdfd,
|
|||
devcnt++;
|
||||
}
|
||||
|
||||
if (super)
|
||||
free(super);
|
||||
super = NULL;
|
||||
|
||||
if (devcnt == 0) {
|
||||
fprintf(stderr, Name ": no devices found for %s\n",
|
||||
mddev);
|
||||
free(first_super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
getinfo_super0(&info, first_super);
|
||||
|
||||
/* now we have some devices that might be suitable.
|
||||
* I wonder how many
|
||||
*/
|
||||
|
@ -398,7 +349,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
/* note: we ignore error flags in multipath arrays
|
||||
* as they don't make sense
|
||||
*/
|
||||
if ((int)first_super.level != -4)
|
||||
if (info.array.level != -4)
|
||||
if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
|
||||
if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
|
||||
sparecnt++;
|
||||
|
@ -407,20 +358,20 @@ int Assemble(char *mddev, int mdfd,
|
|||
if (devices[j].events+event_margin >=
|
||||
devices[most_recent].events) {
|
||||
devices[j].uptodate = 1;
|
||||
if (i < first_super.raid_disks)
|
||||
if (i < info.array.raid_disks)
|
||||
okcnt++;
|
||||
else
|
||||
sparecnt++;
|
||||
}
|
||||
}
|
||||
while (force && !enough(first_super.level, first_super.raid_disks, okcnt)) {
|
||||
while (force && !enough(info.array.level, info.array.raid_disks, okcnt)) {
|
||||
/* Choose the newest best drive which is
|
||||
* not up-to-date, update the superblock
|
||||
* and add it.
|
||||
*/
|
||||
int fd;
|
||||
chosen_drive = -1;
|
||||
for (i=0; i<first_super.raid_disks && i < bestcnt; i++) {
|
||||
for (i=0; i<info.array.raid_disks && i < bestcnt; i++) {
|
||||
int j = best[i];
|
||||
if (j>=0 &&
|
||||
!devices[j].uptodate &&
|
||||
|
@ -442,31 +393,29 @@ int Assemble(char *mddev, int mdfd,
|
|||
devices[chosen_drive].events = 0;
|
||||
continue;
|
||||
}
|
||||
if (load_super(fd, &super)) {
|
||||
if (load_super0(fd, &super, NULL)) {
|
||||
close(fd);
|
||||
fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
|
||||
devices[chosen_drive].devname);
|
||||
devices[chosen_drive].events = 0;
|
||||
continue;
|
||||
}
|
||||
super.events_hi = (devices[most_recent].events>>32)&0xFFFFFFFF;
|
||||
super.events_lo = (devices[most_recent].events)&0xFFFFFFFF;
|
||||
if (super.level == 5 || super.level == 4) {
|
||||
/* need to force clean */
|
||||
super.state = (1<<MD_SB_CLEAN);
|
||||
}
|
||||
super.sb_csum = calc_sb_csum(&super);
|
||||
/*DRYRUN*/ if (store_super(fd, &super)) {
|
||||
info.events = devices[most_recent].events;
|
||||
update_super0(&info, super, "force", devices[chosen_drive].devname, verbose);
|
||||
|
||||
if (store_super0(fd, super)) {
|
||||
close(fd);
|
||||
fprintf(stderr, Name ": Could not re-write superblock on %s\n",
|
||||
devices[chosen_drive].devname);
|
||||
devices[chosen_drive].events = 0;
|
||||
free(super);
|
||||
continue;
|
||||
}
|
||||
close(fd);
|
||||
devices[chosen_drive].events = devices[most_recent].events;
|
||||
devices[chosen_drive].uptodate = 1;
|
||||
okcnt++;
|
||||
free(super);
|
||||
}
|
||||
|
||||
/* Now we want to look at the superblock which the kernel will base things on
|
||||
|
@ -476,9 +425,11 @@ int Assemble(char *mddev, int mdfd,
|
|||
* superblock.
|
||||
*/
|
||||
chosen_drive = -1;
|
||||
super = NULL;
|
||||
for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
|
||||
int j = best[i];
|
||||
int fd;
|
||||
|
||||
if (j<0)
|
||||
continue;
|
||||
if (!devices[j].uptodate)
|
||||
|
@ -489,7 +440,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
devices[j].devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (load_super(fd, &super)) {
|
||||
if (load_super0(fd, &super, NULL)) {
|
||||
close(fd);
|
||||
fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
|
||||
devices[j].devname);
|
||||
|
@ -497,12 +448,16 @@ int Assemble(char *mddev, int mdfd,
|
|||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (super == NULL) {
|
||||
fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
|
||||
return 1;
|
||||
}
|
||||
getinfo_super0(&info, super);
|
||||
for (i=0; i<bestcnt; i++) {
|
||||
int j = best[i];
|
||||
unsigned int desired_state;
|
||||
|
||||
if (i < super.raid_disks)
|
||||
if (i < info.array.raid_disks)
|
||||
desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
|
||||
else
|
||||
desired_state = 0;
|
||||
|
@ -511,77 +466,57 @@ int Assemble(char *mddev, int mdfd,
|
|||
continue;
|
||||
if (!devices[j].uptodate)
|
||||
continue;
|
||||
#if 0
|
||||
This doesnt work yet
|
||||
if (devices[j].major != super.disks[i].major ||
|
||||
devices[j].minor != super.disks[i].minor) {
|
||||
change |= 1;
|
||||
super.disks[i].major = devices[j].major;
|
||||
super.disks[i].minor = devices[j].minor;
|
||||
}
|
||||
#endif
|
||||
if (devices[j].oldmajor != super.disks[i].major ||
|
||||
devices[j].oldminor != super.disks[i].minor) {
|
||||
change |= 2;
|
||||
super.disks[i].major = devices[j].oldmajor;
|
||||
super.disks[i].minor = devices[j].oldminor;
|
||||
}
|
||||
info.disk.number = i;
|
||||
info.disk.state = desired_state;
|
||||
|
||||
if (devices[j].uptodate &&
|
||||
(super.disks[i].state != desired_state)) {
|
||||
update_super0(&info, super, "assemble", NULL, 0)) {
|
||||
if (force) {
|
||||
fprintf(stderr, Name ": "
|
||||
"clearing FAULTY flag for device %d in %s for %s\n",
|
||||
j, mddev, devices[j].devname);
|
||||
super.disks[i].state = desired_state;
|
||||
change |= 2;
|
||||
change = 1;
|
||||
} else {
|
||||
fprintf(stderr, Name ": "
|
||||
"device %d in %s has wrong state in superblock, but %s seems ok\n",
|
||||
i, mddev, devices[j].devname);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (!devices[j].uptodate &&
|
||||
!(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
|
||||
fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
|
||||
i, mddev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (force && (super.level == 4 || super.level == 5) &&
|
||||
okcnt == super.raid_disks-1) {
|
||||
super.state = (1<< MD_SB_CLEAN);
|
||||
change |= 2;
|
||||
if (force && okcnt == info.array.raid_disks-1) {
|
||||
/* FIXME check event count */
|
||||
change += update_super0(&info, super, "force",
|
||||
devices[chosen_drive].devname, 0);
|
||||
}
|
||||
|
||||
if ((force && (change & 2))
|
||||
|| (old_linux && (change & 1))) {
|
||||
if (change) {
|
||||
int fd;
|
||||
super.sb_csum = calc_sb_csum(&super);
|
||||
fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": Could open %s for write - cannot Assemble array.\n",
|
||||
devices[chosen_drive].devname);
|
||||
return 1;
|
||||
}
|
||||
if (store_super(fd, &super)) {
|
||||
if (store_super0(fd, super)) {
|
||||
close(fd);
|
||||
fprintf(stderr, Name ": Could not re-write superblock on %s\n",
|
||||
devices[chosen_drive].devname);
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
change = 0;
|
||||
}
|
||||
|
||||
/* count number of in-sync devices according to the superblock.
|
||||
* We must have this number to start the array without -s or -R
|
||||
*/
|
||||
req_cnt = 0;
|
||||
for (i=0; i<MD_SB_DISKS; i++)
|
||||
if ((first_super.disks[i].state & (1<<MD_DISK_SYNC)) &&
|
||||
(first_super.disks[i].state & (1<<MD_DISK_ACTIVE)) &&
|
||||
!(first_super.disks[i].state & (1<<MD_DISK_FAULTY)))
|
||||
req_cnt ++;
|
||||
|
||||
req_cnt = info.array.working_disks;
|
||||
|
||||
/* Almost ready to actually *do* something */
|
||||
if (!old_linux) {
|
||||
|
@ -610,28 +545,28 @@ This doesnt work yet
|
|||
devices[j].devname,
|
||||
mddev,
|
||||
strerror(errno));
|
||||
if (i < first_super.raid_disks || i == bestcnt)
|
||||
if (i < info.array.raid_disks || i == bestcnt)
|
||||
okcnt--;
|
||||
else
|
||||
sparecnt--;
|
||||
} else if (verbose)
|
||||
fprintf(stderr, Name ": added %s to %s as %d\n",
|
||||
devices[j].devname, mddev, devices[j].raid_disk);
|
||||
} else if (verbose && i < first_super.raid_disks)
|
||||
} else if (verbose && i < info.array.raid_disks)
|
||||
fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
|
||||
i, mddev);
|
||||
}
|
||||
|
||||
if (runstop == 1 ||
|
||||
(runstop == 0 &&
|
||||
( enough(first_super.level, first_super.raid_disks, okcnt) &&
|
||||
( enough(info.array.level, info.array.raid_disks, okcnt) &&
|
||||
(okcnt >= req_cnt || start_partial_ok)
|
||||
))) {
|
||||
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
|
||||
fprintf(stderr, Name ": %s has been started with %d drive%s",
|
||||
mddev, okcnt, okcnt==1?"":"s");
|
||||
if (okcnt < first_super.raid_disks)
|
||||
fprintf(stderr, " (out of %d)", first_super.raid_disks);
|
||||
if (okcnt < info.array.raid_disks)
|
||||
fprintf(stderr, " (out of %d)", info.array.raid_disks);
|
||||
if (sparecnt)
|
||||
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
|
||||
fprintf(stderr, ".\n");
|
||||
|
@ -649,13 +584,13 @@ This doesnt work yet
|
|||
fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
|
||||
if (sparecnt)
|
||||
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
|
||||
if (!enough(first_super.level, first_super.raid_disks, okcnt))
|
||||
if (!enough(info.array.level, info.array.raid_disks, okcnt))
|
||||
fprintf(stderr, " - not enough to start the array.\n");
|
||||
else {
|
||||
if (req_cnt == first_super.raid_disks)
|
||||
if (req_cnt == info.array.raid_disks)
|
||||
fprintf(stderr, " - need all %d to start it", req_cnt);
|
||||
else
|
||||
fprintf(stderr, " - need %d of %d to start", req_cnt, first_super.raid_disks);
|
||||
fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks);
|
||||
fprintf(stderr, " (use --run to insist).\n");
|
||||
}
|
||||
return 1;
|
||||
|
|
95
Create.c
95
Create.c
|
@ -62,7 +62,8 @@ int Create(char *mddev, int mdfd,
|
|||
int first_missing = MD_SB_DISKS*2;
|
||||
int missing_disks = 0;
|
||||
int insert_point = MD_SB_DISKS*2; /* where to insert a missing drive */
|
||||
mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
|
||||
void *super;
|
||||
int pass;
|
||||
|
||||
mdu_array_info_t array;
|
||||
|
||||
|
@ -342,50 +343,70 @@ int Create(char *mddev, int mdfd,
|
|||
array.layout = layout;
|
||||
array.chunk_size = chunk*1024;
|
||||
|
||||
if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
|
||||
if (ioctl(mdfd, SET_ARRAY_INFO, NULL)) {
|
||||
fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (dnum=0, dv = devlist ; dv ; dv=(dv->next)?(dv->next):moved_disk, dnum++) {
|
||||
int fd;
|
||||
struct stat stb;
|
||||
mdu_disk_info_t disk;
|
||||
|
||||
disk.number = dnum;
|
||||
if (dnum == insert_point) {
|
||||
moved_disk = dv;
|
||||
}
|
||||
disk.raid_disk = disk.number;
|
||||
if (disk.raid_disk < raiddisks)
|
||||
disk.state = 6; /* active and in sync */
|
||||
else
|
||||
disk.state = 0;
|
||||
if (dnum == insert_point ||
|
||||
strcasecmp(dv->devname, "missing")==0) {
|
||||
disk.major = 0;
|
||||
disk.minor = 0;
|
||||
disk.state = 1; /* faulty */
|
||||
} else {
|
||||
fd = open(dv->devname, O_RDONLY|O_EXCL, 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
|
||||
dv->devname);
|
||||
return 1;
|
||||
init_super0(&super, &array);
|
||||
|
||||
|
||||
for (pass=1; pass <=2 ; pass++) {
|
||||
mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
|
||||
|
||||
for (dnum=0, dv = devlist ; dv ;
|
||||
dv=(dv->next)?(dv->next):moved_disk, dnum++) {
|
||||
int fd;
|
||||
struct stat stb;
|
||||
mdu_disk_info_t disk;
|
||||
|
||||
disk.number = dnum;
|
||||
if (dnum == insert_point) {
|
||||
moved_disk = dv;
|
||||
}
|
||||
fstat(fd, &stb);
|
||||
disk.major = major(stb.st_rdev);
|
||||
disk.minor = minor(stb.st_rdev);
|
||||
close(fd);
|
||||
disk.raid_disk = disk.number;
|
||||
if (disk.raid_disk < raiddisks)
|
||||
disk.state = 6; /* active and in sync */
|
||||
else
|
||||
disk.state = 0;
|
||||
if (dnum == insert_point ||
|
||||
strcasecmp(dv->devname, "missing")==0) {
|
||||
disk.major = 0;
|
||||
disk.minor = 0;
|
||||
disk.state = 1; /* faulty */
|
||||
} else {
|
||||
fd = open(dv->devname, O_RDONLY|O_EXCL, 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
|
||||
dv->devname);
|
||||
return 1;
|
||||
}
|
||||
fstat(fd, &stb);
|
||||
disk.major = major(stb.st_rdev);
|
||||
disk.minor = minor(stb.st_rdev);
|
||||
close(fd);
|
||||
}
|
||||
switch(pass){
|
||||
case 1:
|
||||
add_to_super0(super, &disk);
|
||||
break;
|
||||
case 2:
|
||||
write_init_super0(super, &disk, dv->devname);
|
||||
|
||||
if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
|
||||
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
|
||||
dv->devname, strerror(errno));
|
||||
free(super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (dv == moved_disk && dnum != insert_point) break;
|
||||
}
|
||||
if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
|
||||
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
|
||||
dv->devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (dv == moved_disk && dnum != insert_point) break;
|
||||
}
|
||||
free(super);
|
||||
|
||||
/* param is not actually used */
|
||||
if (runstop == 1 || subdevs >= raiddisks) {
|
||||
|
|
40
Detail.c
40
Detail.c
|
@ -51,8 +51,7 @@ int Detail(char *dev, int brief, int test)
|
|||
int is_rebuilding = 0;
|
||||
int failed = 0;
|
||||
|
||||
mdp_super_t super;
|
||||
int have_super = 0;
|
||||
void *super = NULL;
|
||||
int rv = test ? 4 : 1;
|
||||
|
||||
if (fd < 0) {
|
||||
|
@ -99,16 +98,21 @@ int Detail(char *dev, int brief, int test)
|
|||
disk.minor == 0)
|
||||
continue;
|
||||
if ((dv=map_dev(disk.major, disk.minor))) {
|
||||
if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
|
||||
if (!super && (disk.state & (1<<MD_DISK_ACTIVE))) {
|
||||
/* try to read the superblock from this device
|
||||
* to get more info
|
||||
*/
|
||||
int fd2 = open(dv, O_RDONLY);
|
||||
if (fd2 >=0 &&
|
||||
load_super(fd2, &super) ==0 &&
|
||||
(unsigned long)super.ctime == (unsigned long)array.ctime &&
|
||||
(unsigned int)super.level == (unsigned int)array.level)
|
||||
have_super = 1;
|
||||
load_super0(fd2, &super, NULL) == 0) {
|
||||
struct mdinfo info;
|
||||
getinfo_super0(&info, super);
|
||||
if (info.array.ctime != array.ctime ||
|
||||
info.array.level != array.level) {
|
||||
free(super);
|
||||
super = NULL;
|
||||
}
|
||||
}
|
||||
if (fd2 >= 0) close(fd2);
|
||||
}
|
||||
}
|
||||
|
@ -198,15 +202,8 @@ int Detail(char *dev, int brief, int test)
|
|||
}
|
||||
free_mdstat(ms);
|
||||
|
||||
if (have_super) {
|
||||
printf(" UUID : ");
|
||||
if (super.minor_version >= 90)
|
||||
printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
|
||||
super.set_uuid2, super.set_uuid3);
|
||||
else
|
||||
printf("%08x", super.set_uuid0);
|
||||
printf("\n Events : %d.%d\n\n", super.events_hi, super.events_lo);
|
||||
}
|
||||
if (super)
|
||||
detail_super0(super);
|
||||
|
||||
printf(" Number Major Minor RaidDevice State\n");
|
||||
}
|
||||
|
@ -278,14 +275,9 @@ int Detail(char *dev, int brief, int test)
|
|||
if (!brief) printf("\n");
|
||||
}
|
||||
if (spares && brief) printf(" spares=%d", spares);
|
||||
if (have_super && brief) {
|
||||
printf(" UUID=");
|
||||
if (super.minor_version >= 90)
|
||||
printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
|
||||
super.set_uuid2, super.set_uuid3);
|
||||
else
|
||||
printf("%08x", super.set_uuid0);
|
||||
}
|
||||
if (super && brief)
|
||||
brief_detail_super0(super);
|
||||
|
||||
if (brief && devices) printf("\n devices=%s", devices);
|
||||
if (brief) printf("\n");
|
||||
if (test && (rv&2)) rv &= ~1;
|
||||
|
|
180
Examine.c
180
Examine.c
|
@ -54,18 +54,16 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
|
|||
* if devlist==NULL, use conf_get_devs(
|
||||
*/
|
||||
int fd;
|
||||
time_t atime;
|
||||
mdp_super_t super;
|
||||
int d;
|
||||
char *c;
|
||||
void *super = NULL;
|
||||
int rv = 0;
|
||||
int err;
|
||||
int spares = 0;
|
||||
|
||||
struct array {
|
||||
mdp_super_t super;
|
||||
void *super;
|
||||
struct mdinfo info;
|
||||
void *devs;
|
||||
struct array *next;
|
||||
int spares;
|
||||
} *arrays = NULL;
|
||||
|
||||
for (; devlist ; devlist=devlist->next) {
|
||||
|
@ -77,48 +75,21 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
|
|||
err = 1;
|
||||
}
|
||||
else {
|
||||
err = load_super(fd, &super);
|
||||
err = load_super0(fd, &super, (brief||scan)?NULL:devlist->devname);
|
||||
close(fd);
|
||||
}
|
||||
if (err && (brief||scan))
|
||||
if (err)
|
||||
continue;
|
||||
if (err) rv =1;
|
||||
switch(err) {
|
||||
case 1:
|
||||
fprintf(stderr, Name ": cannot find device size for %s: %s\n",
|
||||
devlist->devname, strerror(errno));
|
||||
continue;
|
||||
case 2:
|
||||
/* fprintf(stderr, Name ": %s is too small for md: size is %ld sectors\n",
|
||||
devlist->devname, size);
|
||||
*/
|
||||
fprintf(stderr, Name ": %s is too small for md\n",
|
||||
devlist->devname);
|
||||
continue;
|
||||
case 3:
|
||||
fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
|
||||
devlist->devname, strerror(errno));
|
||||
continue;
|
||||
case 4:
|
||||
fprintf(stderr, Name ": Cannot read superblock on %s\n",
|
||||
devlist->devname);
|
||||
continue;
|
||||
case 5:
|
||||
fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
|
||||
devlist->devname, MD_SB_MAGIC, super.md_magic);
|
||||
continue;
|
||||
case 6:
|
||||
fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
|
||||
devlist->devname, super.major_version);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (SparcAdjust)
|
||||
update_super0(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_super(&ap->super, &super)==0)
|
||||
if (compare_super0(&ap->super, super)==0)
|
||||
break;
|
||||
}
|
||||
if (!ap) {
|
||||
|
@ -126,140 +97,37 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
|
|||
ap->super = super;
|
||||
ap->devs = dl_head();
|
||||
ap->next = arrays;
|
||||
ap->spares = 0;
|
||||
arrays = ap;
|
||||
getinfo_super0(&ap->info, super);
|
||||
} else {
|
||||
getinfo_super0(&ap->info, super);
|
||||
free(super);
|
||||
}
|
||||
if (!(ap->info.disk.state & MD_DISK_SYNC))
|
||||
ap->spares++;
|
||||
d = dl_strdup(devlist->devname);
|
||||
dl_add(ap->devs, d);
|
||||
} else {
|
||||
printf("%s:\n",devlist->devname);
|
||||
printf(" Magic : %08x\n", super.md_magic);
|
||||
printf(" Version : %02d.%02d.%02d\n", super.major_version, super.minor_version,
|
||||
super.patch_version);
|
||||
if (super.minor_version >= 90)
|
||||
printf(" UUID : %08x:%08x:%08x:%08x\n", super.set_uuid0, super.set_uuid1,
|
||||
super.set_uuid2, super.set_uuid3);
|
||||
else
|
||||
printf(" UUID : %08x\n", super.set_uuid0);
|
||||
|
||||
atime = super.ctime;
|
||||
printf(" Creation Time : %.24s\n", ctime(&atime));
|
||||
c=map_num(pers, super.level);
|
||||
printf(" Raid Level : %s\n", c?c:"-unknown-");
|
||||
if (super.level <= 0)
|
||||
printf(" Device Size : %u%s\n", super.size, human_size((long long)super.size<<10));
|
||||
printf(" Raid Devices : %d\n", super.raid_disks);
|
||||
printf(" Total Devices : %d\n", super.nr_disks);
|
||||
printf("Preferred Minor : %d\n", super.md_minor);
|
||||
printf("\n");
|
||||
atime = super.utime;
|
||||
printf(" Update Time : %.24s\n", ctime(&atime));
|
||||
printf(" State : %s\n",
|
||||
(super.state&(1<<MD_SB_CLEAN))?"clean":"active");
|
||||
printf(" Active Devices : %d\n", super.active_disks);
|
||||
printf("Working Devices : %d\n", super.working_disks);
|
||||
printf(" Failed Devices : %d\n", super.failed_disks);
|
||||
printf(" Spare Devices : %d\n", super.spare_disks);
|
||||
if (calc_sb_csum(&super) == super.sb_csum)
|
||||
printf(" Checksum : %x - correct\n", super.sb_csum);
|
||||
else
|
||||
printf(" Checksum : %x - expected %lx\n", super.sb_csum, calc_sb_csum(&super));
|
||||
if (SparcAdjust) {
|
||||
/* 2.2 sparc put the events in the wrong place
|
||||
* So we copy the tail of the superblock
|
||||
* up 4 bytes before continuing
|
||||
*/
|
||||
__u32 *sb32 = (__u32*)&super;
|
||||
memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
|
||||
sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
|
||||
(MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
|
||||
printf (" --- adjusting superblock for 2.2/sparc compatability ---\n");
|
||||
}
|
||||
printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
|
||||
if (super.events_hi == super.cp_events_hi &&
|
||||
super.events_lo == super.cp_events_lo &&
|
||||
super.recovery_cp > 0 &&
|
||||
(super.state & (1<<MD_SB_CLEAN)) == 0 )
|
||||
printf("Sync checkpoint : %d KB (%d%%)\n", super.recovery_cp/2, super.recovery_cp/(super.size/100*2));
|
||||
printf("\n");
|
||||
if (super.level == 5) {
|
||||
c = map_num(r5layout, super.layout);
|
||||
printf(" Layout : %s\n", c?c:"-unknown-");
|
||||
}
|
||||
if (super.level == 10)
|
||||
printf(" Layout : near=%d, far=%d\n",
|
||||
super.layout&255, (super.layout>>8) & 255);
|
||||
|
||||
switch(super.level) {
|
||||
case 0:
|
||||
case 4:
|
||||
case 5:
|
||||
printf(" Chunk Size : %dK\n", super.chunk_size/1024);
|
||||
break;
|
||||
case -1:
|
||||
printf(" Rounding : %dK\n", super.chunk_size/1024);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
printf("\n");
|
||||
printf(" Number Major Minor RaidDevice State\n");
|
||||
for (d= -1; d<(signed int)(super.raid_disks+super.spare_disks); d++) {
|
||||
mdp_disk_t *dp;
|
||||
char *dv;
|
||||
char nb[5];
|
||||
if (d>=0) dp = &super.disks[d];
|
||||
else dp = &super.this_disk;
|
||||
sprintf(nb, "%4d", d);
|
||||
printf("%4s %5d %5d %5d %5d ", d < 0 ? "this" : nb,
|
||||
dp->number, dp->major, dp->minor, dp->raid_disk);
|
||||
if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
|
||||
if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
|
||||
if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
|
||||
if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
|
||||
if (dp->state == 0) { printf(" spare"); spares++; }
|
||||
if ((dv=map_dev(dp->major, dp->minor)))
|
||||
printf(" %s", dv);
|
||||
printf("\n");
|
||||
if (d == -1) printf("\n");
|
||||
}
|
||||
}
|
||||
if (SparcAdjust == 2) {
|
||||
printf(" ----- updating superblock on device ----\n");
|
||||
fd = open(devlist->devname, O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": cannot open %s to update superblock: %s\n",
|
||||
devlist->devname, strerror(errno));
|
||||
err = 1;
|
||||
} else {
|
||||
super.sb_csum = calc_sb_csum(&super);
|
||||
if (store_super(fd, &super)) {
|
||||
fprintf(stderr, Name ": Count not re-write superblock on %s\n",
|
||||
devlist->devname);
|
||||
err = 1;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
examine_super0(super);
|
||||
free(super);
|
||||
}
|
||||
}
|
||||
if (brief) {
|
||||
struct array *ap;
|
||||
for (ap=arrays; ap; ap=ap->next) {
|
||||
char sep='=';
|
||||
char *c=map_num(pers, ap->super.level);
|
||||
char *d;
|
||||
printf("ARRAY %s level=%s num-devices=%d UUID=",
|
||||
get_md_name(ap->super.md_minor),
|
||||
c?c:"-unknown-", ap->super.raid_disks);
|
||||
if (spares) printf(" spares=%d", spares);
|
||||
if (ap->super.minor_version >= 90)
|
||||
printf("%08x:%08x:%08x:%08x", ap->super.set_uuid0, ap->super.set_uuid1,
|
||||
ap->super.set_uuid2, ap->super.set_uuid3);
|
||||
else
|
||||
printf("%08x", ap->super.set_uuid0);
|
||||
printf("\n devices");
|
||||
brief_examine_super0(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)) {
|
||||
printf("%c%s", sep, d);
|
||||
sep=',';
|
||||
}
|
||||
free(ap->super);
|
||||
/* FIXME free ap */
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
|
72
Grow.c
72
Grow.c
|
@ -45,20 +45,20 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
* all other devices.
|
||||
* This means that we need to *find* all other devices.
|
||||
*/
|
||||
mdu_array_info_t array;
|
||||
mdu_disk_info_t disk;
|
||||
mdp_super_t super;
|
||||
struct mdinfo info;
|
||||
|
||||
void *super = NULL;
|
||||
struct stat stb;
|
||||
int nfd, fd2;
|
||||
int d, nd;
|
||||
|
||||
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) {
|
||||
fprintf(stderr, Name ": cannot get array info for %s\n", devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (array.level != -1) {
|
||||
if (info.array.level != -1) {
|
||||
fprintf(stderr, Name ": can only add devices to linear arrays\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
return 1;
|
||||
}
|
||||
/* now check out all the devices and make sure we can read the superblock */
|
||||
for (d=0 ; d < array.raid_disks ; d++) {
|
||||
for (d=0 ; d < info.array.raid_disks ; d++) {
|
||||
mdu_disk_info_t disk;
|
||||
char *dv;
|
||||
|
||||
|
@ -96,7 +96,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
fprintf(stderr, Name ": cannot open device file %s\n", dv);
|
||||
return 1;
|
||||
}
|
||||
if (load_super(fd2, &super)) {
|
||||
if (super) free(super);
|
||||
super= NULL;
|
||||
if (load_super0(fd2, &super, NULL)) {
|
||||
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
|
||||
close(fd2);
|
||||
return 1;
|
||||
|
@ -107,27 +109,21 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
* newdev.
|
||||
*/
|
||||
|
||||
memset(&super.disks[d], 0, sizeof(super.disks[d]));
|
||||
super.disks[d].number = d;
|
||||
super.disks[d].major = major(stb.st_rdev);
|
||||
super.disks[d].minor = minor(stb.st_rdev);
|
||||
super.disks[d].raid_disk = d;
|
||||
super.disks[d].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
||||
info.disk.number = d;
|
||||
info.disk.major = major(stb.st_rdev);
|
||||
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);
|
||||
|
||||
super.this_disk = super.disks[d];
|
||||
super.sb_csum = calc_sb_csum(&super);
|
||||
if (store_super(nfd, &super)) {
|
||||
if (store_super0(nfd, super)) {
|
||||
fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
|
||||
close(nfd);
|
||||
return 1;
|
||||
}
|
||||
disk.number = d;
|
||||
disk.major = major(stb.st_rdev);
|
||||
disk.minor = minor(stb.st_rdev);
|
||||
disk.raid_disk = d;
|
||||
disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
||||
close(nfd);
|
||||
if (ioctl(fd, ADD_NEW_DISK, &disk) != 0) {
|
||||
|
||||
if (ioctl(fd, ADD_NEW_DISK, &info.disk) != 0) {
|
||||
fprintf(stderr, Name ": Cannot add new disk to this array\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -135,13 +131,13 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
* Now go through and update all superblocks
|
||||
*/
|
||||
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) {
|
||||
fprintf(stderr, Name ": cannot get array info for %s\n", devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nd = d;
|
||||
for (d=0 ; d < array.raid_disks ; d++) {
|
||||
for (d=0 ; d < info.array.raid_disks ; d++) {
|
||||
mdu_disk_info_t disk;
|
||||
char *dv;
|
||||
|
||||
|
@ -162,25 +158,23 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
fprintf(stderr, Name ": cannot open device file %s\n", dv);
|
||||
return 1;
|
||||
}
|
||||
if (load_super(fd2, &super)) {
|
||||
if (load_super0(fd2, &super, NULL)) {
|
||||
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
super.raid_disks = nd+1;
|
||||
super.nr_disks = nd+1;
|
||||
super.active_disks = nd+1;
|
||||
super.working_disks = nd+1;
|
||||
memset(&super.disks[nd], 0, sizeof(super.disks[nd]));
|
||||
super.disks[nd].number = nd;
|
||||
super.disks[nd].major = major(stb.st_rdev);
|
||||
super.disks[nd].minor = minor(stb.st_rdev);
|
||||
super.disks[nd].raid_disk = nd;
|
||||
super.disks[nd].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
||||
|
||||
super.this_disk = super.disks[d];
|
||||
super.sb_csum = calc_sb_csum(&super);
|
||||
if (store_super(fd2, &super)) {
|
||||
info.array.raid_disks = nd+1;
|
||||
info.array.nr_disks = nd+1;
|
||||
info.array.active_disks = nd+1;
|
||||
info.array.working_disks = nd+1;
|
||||
info.disk.number = nd;
|
||||
info.disk.major = major(stb.st_rdev);
|
||||
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);
|
||||
|
||||
if (store_super0(fd2, super)) {
|
||||
fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
|
||||
close(fd2);
|
||||
return 1;
|
||||
|
|
30
Kill.c
30
Kill.c
|
@ -41,7 +41,7 @@ int Kill(char *dev, int force)
|
|||
* Definitely not safe.
|
||||
*/
|
||||
|
||||
mdp_super_t super;
|
||||
void *super;
|
||||
int fd, rv = 0;
|
||||
|
||||
fd = open(dev, O_RDWR|O_EXCL);
|
||||
|
@ -50,32 +50,18 @@ int Kill(char *dev, int force)
|
|||
dev);
|
||||
return 1;
|
||||
}
|
||||
rv = load_super(fd, &super);
|
||||
if (force && rv >= 5)
|
||||
rv = load_super0(fd, &super, dev);
|
||||
if (force && rv >= 2)
|
||||
rv = 0; /* ignore bad data in superblock */
|
||||
switch(rv) {
|
||||
case 1:
|
||||
fprintf(stderr, Name ": cannot file device size for %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
break;
|
||||
case 2:
|
||||
fprintf(stderr, Name ": %s is too small for md.\n", dev);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
fprintf(stderr, Name ": cannot access superblock on %s.\n", dev);
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
fprintf(stderr, Name ": %s does not appear to have an MD superblock.\n", dev);
|
||||
break;
|
||||
}
|
||||
if (!rv) {
|
||||
if (rv== 0 || (force && rv >= 2)) {
|
||||
memset(&super, 0, sizeof(super));
|
||||
if (store_super(fd, &super)) {
|
||||
if (store_super0(fd, super)) {
|
||||
fprintf(stderr, Name ": Could not zero superblock on %s\n",
|
||||
dev);
|
||||
rv = 1;
|
||||
} else if (rv) {
|
||||
fprintf(stderr, Name ": superblock zeroed anyway\n");
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
|
5
Makefile
5
Makefile
|
@ -58,9 +58,10 @@ MAN5DIR = $(MANDIR)/man5
|
|||
MAN8DIR = $(MANDIR)/man8
|
||||
|
||||
OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o \
|
||||
Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o mdopen.o
|
||||
Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o mdopen.o super0.o
|
||||
SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c \
|
||||
Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c mdopen.c
|
||||
Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c mdopen.c super0.c
|
||||
|
||||
ASSEMBLE_SRCS := mdassemble.c Assemble.c config.c dlink.c util.c
|
||||
ifdef MDASSEMBLE_AUTO
|
||||
ASSEMBLE_SRCS += mdopen.c mdstat.c
|
||||
|
|
49
Query.c
49
Query.c
|
@ -41,8 +41,10 @@ int Query(char *dev)
|
|||
int vers;
|
||||
int ioctlerr;
|
||||
int superror, superrno;
|
||||
mdp_super_t super;
|
||||
struct mdinfo info;
|
||||
mdu_array_info_t array;
|
||||
void *super;
|
||||
|
||||
unsigned long long larray_size;
|
||||
unsigned long array_size;
|
||||
struct stat stb;
|
||||
|
@ -60,8 +62,6 @@ int Query(char *dev)
|
|||
if (ioctl(fd, GET_ARRAY_INFO, &array)<0)
|
||||
ioctlerr = errno;
|
||||
else ioctlerr = 0;
|
||||
superror = load_super(fd, &super);
|
||||
superrno = errno;
|
||||
|
||||
fstat(fd, &stb);
|
||||
|
||||
|
@ -76,7 +76,6 @@ int Query(char *dev)
|
|||
larray_size <<= 9;
|
||||
} else larray_size = 0;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (vers < 0)
|
||||
printf("%s: is not an md array\n", dev);
|
||||
|
@ -95,35 +94,14 @@ int Query(char *dev)
|
|||
array.raid_disks,
|
||||
array.spare_disks, array.spare_disks==1?"":"s");
|
||||
}
|
||||
switch(superror) {
|
||||
case 1:
|
||||
printf("%s: cannot find device size: %s\n",
|
||||
dev, strerror(superrno));
|
||||
break;
|
||||
case 2:
|
||||
printf("%s: is too small to be an md component.\n",
|
||||
dev);
|
||||
break;
|
||||
case 3:
|
||||
printf("%s: Cannot seek to superblock: %s\n",
|
||||
dev, strerror(superrno));
|
||||
break;
|
||||
case 4:
|
||||
printf("%s: Cannot read md superblock.\n",
|
||||
dev);
|
||||
break;
|
||||
case 5:
|
||||
printf("%s: No md super block found, not an md component.\n",
|
||||
dev);
|
||||
break;
|
||||
case 6:
|
||||
printf("%s: md superblock present with wrong version: %d\n",
|
||||
dev, super.major_version);
|
||||
break;
|
||||
default:
|
||||
superror = load_super0(fd, &super, dev);
|
||||
superrno = errno;
|
||||
close(fd);
|
||||
if (superror == 0) {
|
||||
/* array might be active... */
|
||||
mddev = get_md_name(super.md_minor);
|
||||
disc.number = super.this_disk.number;
|
||||
getinfo_super0(&info, super);
|
||||
mddev = get_md_name(info.array.md_minor);
|
||||
disc.number = info.disk.number;
|
||||
activity = "undetected";
|
||||
if (mddev && (fd = open(mddev, O_RDONLY))>=0) {
|
||||
if (md_get_version(fd) >= 9000 &&
|
||||
|
@ -138,11 +116,10 @@ int Query(char *dev)
|
|||
}
|
||||
printf("%s: device %d in %d device %s %s md%d. Use mdadm --examine for more detail.\n",
|
||||
dev,
|
||||
super.this_disk.number, super.raid_disks,
|
||||
info.disk.number, info.array.raid_disks,
|
||||
activity,
|
||||
map_num(pers, super.level),
|
||||
super.md_minor);
|
||||
break;
|
||||
map_num(pers, info.array.level),
|
||||
info.array.md_minor);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
1
ReadMe.c
1
ReadMe.c
|
@ -30,6 +30,7 @@
|
|||
#include "mdadm.h"
|
||||
|
||||
char Version[] = Name " - v1.11.0 - 11 April 2005\n";
|
||||
|
||||
/*
|
||||
* File: ReadMe.c
|
||||
*
|
||||
|
|
28
mdadm.h
28
mdadm.h
|
@ -65,6 +65,14 @@ char *strncpy(char *dest, const char *src, size_t n) __THROW;
|
|||
#include "md_u.h"
|
||||
#include "md_p.h"
|
||||
|
||||
/* general information that might be extracted from a superblock */
|
||||
struct mdinfo {
|
||||
mdu_array_info_t array;
|
||||
mdu_disk_info_t disk;
|
||||
__u64 events;
|
||||
unsigned int uuid[4];
|
||||
};
|
||||
|
||||
#define Name "mdadm"
|
||||
|
||||
enum mode {
|
||||
|
@ -211,11 +219,10 @@ extern char *conf_line(FILE *file);
|
|||
extern char *conf_word(FILE *file, int allow_key);
|
||||
extern void free_line(char *line);
|
||||
extern int match_oneof(char *devices, char *devname);
|
||||
extern int load_super(int fd, mdp_super_t *super);
|
||||
extern void uuid_from_super(int uuid[4], mdp_super_t *super);
|
||||
extern int same_uuid(int a[4], int b[4]);
|
||||
extern int compare_super(mdp_super_t *first, mdp_super_t *second);
|
||||
extern unsigned long calc_sb_csum(mdp_super_t *super);
|
||||
/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
|
||||
extern unsigned long calc_csum(void *super, int bytes);
|
||||
extern int store_super(int fd, mdp_super_t *super);
|
||||
extern int enough(int level, int raid_disks, int avail_disks);
|
||||
extern int ask(char *mesg);
|
||||
|
@ -255,3 +262,18 @@ 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);
|
||||
|
|
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* mdadm - manage Linux "md" devices aka RAID arrays.
|
||||
*
|
||||
* Copyright (C) 2001-2004 Neil Brown <neilb@cse.unsw.edu.au>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Neil Brown
|
||||
* Email: <neilb@cse.unsw.edu.au>
|
||||
* Paper: Neil Brown
|
||||
* School of Computer Science and Engineering
|
||||
* The University of New South Wales
|
||||
* Sydney, 2052
|
||||
* Australia
|
||||
*/
|
||||
|
||||
#include "mdadm.h"
|
||||
|
||||
/*
|
||||
* All handling for the 0.90.0 version superblock is in
|
||||
* this file.
|
||||
* This includes:
|
||||
* - finding, loading, and writing the superblock.
|
||||
* - initialising a new superblock
|
||||
* - printing the superblock for --examine
|
||||
* - printing part of the superblock for --detail
|
||||
* .. other stuff
|
||||
*/
|
||||
|
||||
|
||||
static unsigned long calc_sb0_csum(mdp_super_t *super)
|
||||
{
|
||||
unsigned long csum = super->sb_csum;
|
||||
unsigned long newcsum;
|
||||
super->sb_csum= 0 ;
|
||||
newcsum = calc_csum(super, MD_SB_BYTES);
|
||||
super->sb_csum = csum;
|
||||
return newcsum;
|
||||
}
|
||||
|
||||
void examine_super0(void *sbv)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
time_t atime;
|
||||
int d;
|
||||
char *c;
|
||||
|
||||
printf(" Magic : %08x\n", sb->md_magic);
|
||||
printf(" Version : %02d.%02d.%02d\n", sb->major_version, sb->minor_version,
|
||||
sb->patch_version);
|
||||
if (sb->minor_version >= 90)
|
||||
printf(" UUID : %08x:%08x:%08x:%08x\n", sb->set_uuid0, sb->set_uuid1,
|
||||
sb->set_uuid2, sb->set_uuid3);
|
||||
else
|
||||
printf(" UUID : %08x\n", sb->set_uuid0);
|
||||
|
||||
atime = sb->ctime;
|
||||
printf(" Creation Time : %.24s\n", ctime(&atime));
|
||||
c=map_num(pers, sb->level);
|
||||
printf(" Raid Level : %s\n", c?c:"-unknown-");
|
||||
if ((int)sb->level >= 0)
|
||||
printf(" Device Size : %d%s\n", sb->size, human_size((long long)sb->size<<10));
|
||||
printf(" Raid Devices : %d\n", sb->raid_disks);
|
||||
printf(" Total Devices : %d\n", sb->nr_disks);
|
||||
printf("Preferred Minor : %d\n", sb->md_minor);
|
||||
printf("\n");
|
||||
atime = sb->utime;
|
||||
printf(" Update Time : %.24s\n", ctime(&atime));
|
||||
printf(" State : %s\n",
|
||||
(sb->state&(1<<MD_SB_CLEAN))?"clean":"active");
|
||||
printf(" Active Devices : %d\n", sb->active_disks);
|
||||
printf("Working Devices : %d\n", sb->working_disks);
|
||||
printf(" Failed Devices : %d\n", sb->failed_disks);
|
||||
printf(" Spare Devices : %d\n", sb->spare_disks);
|
||||
if (calc_sb0_csum(sb) == sb->sb_csum)
|
||||
printf(" Checksum : %x - correct\n", sb->sb_csum);
|
||||
else
|
||||
printf(" Checksum : %x - expected %lx\n", sb->sb_csum, calc_sb0_csum(sb));
|
||||
printf(" Events : %d.%d\n", sb->events_hi, sb->events_lo);
|
||||
printf("\n");
|
||||
if (sb->level == 5) {
|
||||
c = map_num(r5layout, sb->layout);
|
||||
printf(" Layout : %s\n", c?c:"-unknown-");
|
||||
}
|
||||
switch(sb->level) {
|
||||
case 0:
|
||||
case 4:
|
||||
case 5:
|
||||
printf(" Chunk Size : %dK\n", sb->chunk_size/1024);
|
||||
break;
|
||||
case -1:
|
||||
printf(" Rounding : %dK\n", sb->chunk_size/1024);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
printf("\n");
|
||||
printf(" Number Major Minor RaidDevice State\n");
|
||||
for (d= -1; d<(signed int)(sb->raid_disks+sb->spare_disks); d++) {
|
||||
mdp_disk_t *dp;
|
||||
char *dv;
|
||||
char nb[5];
|
||||
if (d>=0) dp = &sb->disks[d];
|
||||
else dp = &sb->this_disk;
|
||||
sprintf(nb, "%4d", d);
|
||||
printf("%4s %5d %5d %5d %5d ", d < 0 ? "this" : nb,
|
||||
dp->number, dp->major, dp->minor, dp->raid_disk);
|
||||
if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
|
||||
if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
|
||||
if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
|
||||
if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
|
||||
if (dp->state == 0) printf(" spare");
|
||||
if ((dv=map_dev(dp->major, dp->minor)))
|
||||
printf(" %s", dv);
|
||||
printf("\n");
|
||||
if (d == -1) printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void brief_examine_super0(void *sbv)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
char *c=map_num(pers, sb->level);
|
||||
|
||||
printf("ARRAY %s level=%s num-devices=%d UUID=",
|
||||
get_md_name(sb->md_minor),
|
||||
c?c:"-unknown-", sb->raid_disks);
|
||||
if (sb->minor_version >= 90)
|
||||
printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
|
||||
sb->set_uuid2, sb->set_uuid3);
|
||||
else
|
||||
printf("%08x", sb->set_uuid0);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void detail_super0(void *sbv)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
printf(" UUID : ");
|
||||
if (sb->minor_version >= 90)
|
||||
printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
|
||||
sb->set_uuid2, sb->set_uuid3);
|
||||
else
|
||||
printf("%08x", sb->set_uuid0);
|
||||
printf("\n Events : %d.%d\n\n", sb->events_hi, sb->events_lo);
|
||||
}
|
||||
|
||||
void brief_detail_super0(void *sbv)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
printf(" UUID=");
|
||||
if (sb->minor_version >= 90)
|
||||
printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
|
||||
sb->set_uuid2, sb->set_uuid3);
|
||||
else
|
||||
printf("%08x", sb->set_uuid0);
|
||||
}
|
||||
|
||||
void uuid_from_super0(int uuid[4], void * sbv)
|
||||
{
|
||||
mdp_super_t *super = sbv;
|
||||
uuid[0] = super->set_uuid0;
|
||||
if (super->minor_version >= 90) {
|
||||
uuid[1] = super->set_uuid1;
|
||||
uuid[2] = super->set_uuid2;
|
||||
uuid[3] = super->set_uuid3;
|
||||
} else {
|
||||
uuid[1] = 0;
|
||||
uuid[2] = 0;
|
||||
uuid[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void getinfo_super0(struct mdinfo *info, void *sbv)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
int working = 0;
|
||||
int i;
|
||||
|
||||
info->array.major_version = sb->major_version;
|
||||
info->array.minor_version = sb->minor_version;
|
||||
info->array.patch_version = sb->patch_version;
|
||||
info->array.raid_disks = sb->raid_disks;
|
||||
info->array.level = sb->level;
|
||||
info->array.md_minor = sb->md_minor;
|
||||
info->array.ctime = sb->ctime;
|
||||
|
||||
info->disk.state = sb->this_disk.state;
|
||||
info->disk.major = sb->this_disk.major;
|
||||
info->disk.minor = sb->this_disk.minor;
|
||||
info->disk.raid_disk = sb->this_disk.raid_disk;
|
||||
|
||||
info->events = md_event(sb);
|
||||
|
||||
uuid_from_super0(info->uuid, sbv);
|
||||
|
||||
/* work_disks is calculated rather than read directly */
|
||||
for (i=0; i < MD_SB_DISKS; i++)
|
||||
if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
|
||||
(sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
|
||||
!(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
|
||||
working ++;
|
||||
info->array.working_disks = working;
|
||||
}
|
||||
|
||||
|
||||
int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
|
||||
{
|
||||
int rv = 0;
|
||||
mdp_super_t *sb = sbv;
|
||||
if (strcmp(update, "sparc2.2")==0 ) {
|
||||
/* 2.2 sparc put the events in the wrong place
|
||||
* So we copy the tail of the superblock
|
||||
* up 4 bytes before continuing
|
||||
*/
|
||||
__u32 *sb32 = (__u32*)sb;
|
||||
memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
|
||||
sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
|
||||
(MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
|
||||
fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
|
||||
devname);
|
||||
}
|
||||
if (strcmp(update, "super-minor") ==0) {
|
||||
sb->md_minor = info->array.md_minor;
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
|
||||
devname, info->array.md_minor);
|
||||
}
|
||||
if (strcmp(update, "summaries") == 0) {
|
||||
int i;
|
||||
/* set nr_disks, active_disks, working_disks,
|
||||
* failed_disks, spare_disks based on disks[]
|
||||
* array in superblock.
|
||||
* Also make sure extra slots aren't 'failed'
|
||||
*/
|
||||
sb->nr_disks = sb->active_disks =
|
||||
sb->working_disks = sb->failed_disks =
|
||||
sb->spare_disks = 0;
|
||||
for (i=0; i < MD_SB_DISKS ; i++)
|
||||
if (sb->disks[i].major ||
|
||||
sb->disks[i].minor) {
|
||||
int state = sb->disks[i].state;
|
||||
if (state & (1<<MD_DISK_REMOVED))
|
||||
continue;
|
||||
sb->nr_disks++;
|
||||
if (state & (1<<MD_DISK_ACTIVE))
|
||||
sb->active_disks++;
|
||||
if (state & (1<<MD_DISK_FAULTY))
|
||||
sb->failed_disks++;
|
||||
else
|
||||
sb->working_disks++;
|
||||
if (state == 0)
|
||||
sb->spare_disks++;
|
||||
} else if (i >= sb->raid_disks && sb->disks[i].number == 0)
|
||||
sb->disks[i].state = 0;
|
||||
}
|
||||
if (strcmp(update, "force")==0) {
|
||||
sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
|
||||
sb->events_lo = (info->events) & 0xFFFFFFFF;
|
||||
if (sb->level == 5 || sb->level == 4 || sb->level == 6)
|
||||
/* need to force clean */
|
||||
sb->state |= (1 << MD_SB_CLEAN);
|
||||
}
|
||||
if (strcmp(update, "assemble")==0) {
|
||||
int d = info->disk.number;
|
||||
if (sb->disks[d].state != info->disk.state) {
|
||||
sb->disks[d].state = info->disk.state;
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
if (strcmp(update, "newdev") == 0) {
|
||||
int d = info->disk.number;
|
||||
memset(&sb->disks[d], 0, sizeof(sb->disks[d]));
|
||||
sb->disks[d].number = d;
|
||||
sb->disks[d].major = info->disk.major;
|
||||
sb->disks[d].minor = info->disk.minor;
|
||||
sb->disks[d].raid_disk = info->disk.raid_disk;
|
||||
sb->disks[d].state = info->disk.state;
|
||||
sb->this_disk = sb->disks[d];
|
||||
}
|
||||
if (strcmp(update, "grow") == 0) {
|
||||
sb->raid_disks = info->array.raid_disks;
|
||||
sb->nr_disks = info->array.nr_disks;
|
||||
sb->active_disks = info->array.active_disks;
|
||||
sb->working_disks = info->array.working_disks;
|
||||
memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
|
||||
sb->disks[info->disk.number].number = info->disk.number;
|
||||
sb->disks[info->disk.number].major = info->disk.major;
|
||||
sb->disks[info->disk.number].minor = info->disk.minor;
|
||||
sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
|
||||
sb->disks[info->disk.number].state = info->disk.state;
|
||||
if (sb->this_disk.number == info->disk.number)
|
||||
sb->this_disk = sb->disks[info->disk.number];
|
||||
}
|
||||
if (strcmp(update, "resync") == 0) {
|
||||
/* make sure resync happens */
|
||||
sb->state &= ~(1<<MD_SB_CLEAN);
|
||||
sb->recovery_cp = 0;
|
||||
}
|
||||
|
||||
sb->sb_csum = calc_sb0_csum(sb);
|
||||
return rv;
|
||||
}
|
||||
|
||||
__u64 event_super0(void *sbv)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
return md_event(sb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void init_super0(void **sbp, mdu_array_info_t *info)
|
||||
{
|
||||
mdp_super_t *sb = malloc(MD_SB_BYTES);
|
||||
memset(sb, 0, MD_SB_BYTES);
|
||||
|
||||
sb->md_magic = MD_SB_MAGIC;
|
||||
sb->major_version = 0;
|
||||
sb->minor_version = 90;
|
||||
sb->patch_version = 0;
|
||||
sb->gvalid_words = 0; /* ignored */
|
||||
sb->set_uuid0 = random();
|
||||
sb->ctime = time(0);
|
||||
sb->level = info->level;
|
||||
sb->size = info->size;
|
||||
sb->nr_disks = info->nr_disks;
|
||||
sb->raid_disks = info->raid_disks;
|
||||
sb->md_minor = info->md_minor;
|
||||
sb->not_persistent = 0;
|
||||
sb->set_uuid1 = random();
|
||||
sb->set_uuid2 = random();
|
||||
sb->set_uuid3 = random();
|
||||
|
||||
sb->utime = sb->ctime;
|
||||
sb->state = info->state;
|
||||
sb->active_disks = info->active_disks;
|
||||
sb->working_disks = info->working_disks;
|
||||
sb->failed_disks = info->failed_disks;
|
||||
sb->events_hi = 0;
|
||||
sb->events_lo = 1;
|
||||
|
||||
sb->layout = info->layout;
|
||||
sb->chunk_size = info->chunk_size;
|
||||
|
||||
*sbp = sb;
|
||||
}
|
||||
|
||||
/* Add a device to the superblock being created */
|
||||
void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
|
||||
{
|
||||
mdp_super_t *sb = sbv;
|
||||
mdp_disk_t *dk = &sb->disks[dinfo->number];
|
||||
|
||||
dk->number = dinfo->number;
|
||||
dk->major = dinfo->major;
|
||||
dk->minor = dinfo->minor;
|
||||
dk->raid_disk = dinfo->raid_disk;
|
||||
dk->state = dinfo->state;
|
||||
}
|
||||
|
||||
int store_super0(int fd, mdp_super_t *super)
|
||||
{
|
||||
unsigned long size;
|
||||
unsigned long long dsize;
|
||||
unsigned long long offset;
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
|
||||
#endif
|
||||
{
|
||||
if (ioctl(fd, BLKGETSIZE, &size))
|
||||
return 1;
|
||||
else
|
||||
dsize = ((unsigned long long)size)<<9;
|
||||
}
|
||||
|
||||
if (dsize < MD_RESERVED_SECTORS*2)
|
||||
return 2;
|
||||
|
||||
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
|
||||
|
||||
offset *= 512;
|
||||
|
||||
if (lseek64(fd, offset, 0)< 0LL)
|
||||
return 3;
|
||||
|
||||
if (write(fd, super, sizeof(*super)) != sizeof(*super))
|
||||
return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
int rv;
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": Failed to open %s to write superblock\n", devname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sb->this_disk = sb->disks[dinfo->number];
|
||||
sb->sb_csum = calc_sb0_csum(sb);
|
||||
rv = store_super0(fd, sb);
|
||||
close(fd);
|
||||
if (rv)
|
||||
fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int compare_super0(void **firstp, void *secondv)
|
||||
{
|
||||
/*
|
||||
* return:
|
||||
* 0 same, or first was empty, and second was copied
|
||||
* 1 second had wrong number
|
||||
* 2 wrong uuid
|
||||
* 3 wrong other info
|
||||
*/
|
||||
mdp_super_t *first = *firstp;
|
||||
mdp_super_t *second = secondv;
|
||||
|
||||
int uuid1[4], uuid2[4];
|
||||
if (second->md_magic != MD_SB_MAGIC)
|
||||
return 1;
|
||||
if (!first) {
|
||||
first = malloc(MD_SB_BYTES);
|
||||
memcpy(first, second, MD_SB_BYTES);
|
||||
*firstp = first;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid_from_super0(uuid1, first);
|
||||
uuid_from_super0(uuid2, second);
|
||||
if (!same_uuid(uuid1, uuid2))
|
||||
return 2;
|
||||
if (first->major_version != second->major_version ||
|
||||
first->minor_version != second->minor_version ||
|
||||
first->patch_version != second->patch_version ||
|
||||
first->gvalid_words != second->gvalid_words ||
|
||||
first->ctime != second->ctime ||
|
||||
first->level != second->level ||
|
||||
first->size != second->size ||
|
||||
first->raid_disks != second->raid_disks )
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int load_super0(int fd, void **sbp, char *devname)
|
||||
{
|
||||
/* try to read in the superblock
|
||||
* Return:
|
||||
* 0 on success
|
||||
* 1 on cannot get superblock
|
||||
* 2 on superblock meaningless
|
||||
*/
|
||||
unsigned long size;
|
||||
unsigned long long dsize;
|
||||
unsigned long long offset;
|
||||
mdp_super_t *super;
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
|
||||
#endif
|
||||
{
|
||||
if (ioctl(fd, BLKGETSIZE, &size)) {
|
||||
if (devname)
|
||||
fprintf(stderr, Name ": cannot find device size for %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
return 1;
|
||||
} else
|
||||
dsize = size << 9;
|
||||
}
|
||||
|
||||
if (dsize < MD_RESERVED_SECTORS*2) {
|
||||
if (devname)
|
||||
fprintf(stderr, Name ": %s is too small for md: size is %ld sectors.\n",
|
||||
devname, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
|
||||
|
||||
offset *= 512;
|
||||
|
||||
ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
|
||||
|
||||
if (lseek64(fd, offset, 0)< 0LL) {
|
||||
if (devname)
|
||||
fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
super = malloc(MD_SB_BYTES);
|
||||
|
||||
if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
|
||||
if (devname)
|
||||
fprintf(stderr, Name ": Cannot read superblock on %s\n",
|
||||
devname);
|
||||
free(super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (super->md_magic != MD_SB_MAGIC) {
|
||||
if (devname)
|
||||
fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
|
||||
devname, MD_SB_MAGIC, super->md_magic);
|
||||
free(super);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (super->major_version != 0) {
|
||||
if (devname)
|
||||
fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
|
||||
devname, super->major_version);
|
||||
free(super);
|
||||
return 2;
|
||||
}
|
||||
*sbp = super;
|
||||
return 0;
|
||||
}
|
160
util.c
160
util.c
|
@ -150,140 +150,6 @@ int same_uuid(int a[4], int b[4])
|
|||
return 0;
|
||||
}
|
||||
|
||||
void uuid_from_super(int uuid[4], mdp_super_t *super)
|
||||
{
|
||||
uuid[0] = super->set_uuid0;
|
||||
if (super->minor_version >= 90) {
|
||||
uuid[1] = super->set_uuid1;
|
||||
uuid[2] = super->set_uuid2;
|
||||
uuid[3] = super->set_uuid3;
|
||||
} else {
|
||||
uuid[1] = 0;
|
||||
uuid[2] = 0;
|
||||
uuid[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int compare_super(mdp_super_t *first, mdp_super_t *second)
|
||||
{
|
||||
/*
|
||||
* return:
|
||||
* 0 same, or first was empty, and second was copied
|
||||
* 1 second had wrong number
|
||||
* 2 wrong uuid
|
||||
* 3 wrong other info
|
||||
*/
|
||||
int uuid1[4], uuid2[4];
|
||||
if (second->md_magic != MD_SB_MAGIC)
|
||||
return 1;
|
||||
if (first-> md_magic != MD_SB_MAGIC) {
|
||||
memcpy(first, second, sizeof(*first));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid_from_super(uuid1, first);
|
||||
uuid_from_super(uuid2, second);
|
||||
if (!same_uuid(uuid1, uuid2))
|
||||
return 2;
|
||||
if (first->major_version != second->major_version ||
|
||||
first->minor_version != second->minor_version ||
|
||||
first->patch_version != second->patch_version ||
|
||||
first->gvalid_words != second->gvalid_words ||
|
||||
first->ctime != second->ctime ||
|
||||
first->level != second->level ||
|
||||
first->size != second->size ||
|
||||
first->raid_disks != second->raid_disks )
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_super(int fd, mdp_super_t *super)
|
||||
{
|
||||
/* try to read in the superblock
|
||||
*
|
||||
* return
|
||||
* 0 - success
|
||||
* 1 - no block size
|
||||
* 2 - too small
|
||||
* 3 - no seek
|
||||
* 4 - no read
|
||||
* 5 - no magic
|
||||
* 6 - wrong major version
|
||||
*/
|
||||
unsigned long size;
|
||||
unsigned long long dsize;
|
||||
unsigned long long offset;
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
|
||||
#endif
|
||||
{
|
||||
if (ioctl(fd, BLKGETSIZE, &size))
|
||||
return 1;
|
||||
else
|
||||
dsize = size << 9;
|
||||
}
|
||||
|
||||
if (dsize < MD_RESERVED_SECTORS*2)
|
||||
return 2;
|
||||
|
||||
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
|
||||
|
||||
offset *= 512;
|
||||
|
||||
ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
|
||||
|
||||
if (lseek64(fd, offset, 0)< 0LL)
|
||||
return 3;
|
||||
|
||||
if (read(fd, super, sizeof(*super)) != sizeof(*super))
|
||||
return 4;
|
||||
|
||||
if (super->md_magic != MD_SB_MAGIC)
|
||||
return 5;
|
||||
|
||||
if (super->major_version != 0)
|
||||
return 6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int store_super(int fd, mdp_super_t *super)
|
||||
{
|
||||
unsigned long size;
|
||||
unsigned long long dsize;
|
||||
|
||||
long long offset;
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
|
||||
#endif
|
||||
{
|
||||
if (ioctl(fd, BLKGETSIZE, &size))
|
||||
return 1;
|
||||
else
|
||||
dsize = ((unsigned long long)size) << 9;
|
||||
}
|
||||
|
||||
if (dsize < MD_RESERVED_SECTORS*2)
|
||||
return 2;
|
||||
|
||||
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
|
||||
|
||||
offset *= 512;
|
||||
|
||||
if (lseek64(fd, offset, 0)< 0LL)
|
||||
return 3;
|
||||
|
||||
if (write(fd, super, sizeof(*super)) != sizeof(*super))
|
||||
return 4;
|
||||
|
||||
fsync(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int check_ext2(int fd, char *name)
|
||||
{
|
||||
/*
|
||||
|
@ -339,18 +205,25 @@ 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)
|
||||
{
|
||||
mdp_super_t super;
|
||||
void *super;
|
||||
struct mdinfo info;
|
||||
time_t crtime;
|
||||
if (load_super(fd, &super))
|
||||
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);
|
||||
crtime = super.ctime;
|
||||
getinfo_super0(&info, super);
|
||||
free(super);
|
||||
crtime = info.array.ctime;
|
||||
fprintf(stderr, " level=%d devices=%d ctime=%s",
|
||||
super.level, super.raid_disks, ctime(&crtime));
|
||||
info.array.level, info.array.raid_disks, ctime(&crtime));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -506,19 +379,16 @@ char *map_dev(int major, int minor)
|
|||
|
||||
#endif
|
||||
|
||||
unsigned long calc_sb_csum(mdp_super_t *super)
|
||||
unsigned long calc_csum(void *super, int bytes)
|
||||
{
|
||||
unsigned int oldcsum = super->sb_csum;
|
||||
unsigned long long newcsum = 0;
|
||||
unsigned long csum;
|
||||
int i;
|
||||
unsigned int *superc = (int*) super;
|
||||
super->sb_csum = 0;
|
||||
unsigned int csum;
|
||||
unsigned int *superc = (unsigned int*) super;
|
||||
|
||||
for(i=0; i<MD_SB_BYTES/4; i++)
|
||||
for(i=0; i<bytes/4; i++)
|
||||
newcsum+= superc[i];
|
||||
csum = (newcsum& 0xffffffff) + (newcsum>>32);
|
||||
super->sb_csum = oldcsum;
|
||||
return csum;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue