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
237
Assemble.c
237
Assemble.c
|
@ -28,8 +28,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mdadm.h"
|
#include "mdadm.h"
|
||||||
#include "md_u.h"
|
|
||||||
#include "md_p.h"
|
|
||||||
|
|
||||||
int Assemble(char *mddev, int mdfd,
|
int Assemble(char *mddev, int mdfd,
|
||||||
mddev_ident_t ident, char *conffile,
|
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
|
* Much of the work of Assemble is in finding and/or
|
||||||
* checking the disks to make sure they look right.
|
* 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
|
* read through the config file for dev+uuid mapping
|
||||||
* We recurse, setting mddev, for each device that
|
* We recurse, setting mddev, for each device that
|
||||||
* - isn't running
|
* - 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.
|
* If mddev is set, we try to determine state of md.
|
||||||
* check version - must be at least 0.90.0
|
* 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 superblock - discard if bad
|
||||||
* Check uuid (set if we don't have one) - discard if no match
|
* Check uuid (set if we don't have one) - discard if no match
|
||||||
* Check superblock similarity if we have a superblock - discard if different
|
* 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
|
* 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
|
* Count disks with recent enough event count
|
||||||
* While force && !enough disks
|
* While force && !enough disks
|
||||||
|
@ -94,14 +92,12 @@ int Assemble(char *mddev, int mdfd,
|
||||||
*/
|
*/
|
||||||
int old_linux = 0;
|
int old_linux = 0;
|
||||||
int vers;
|
int vers;
|
||||||
mdu_array_info_t array;
|
void *first_super = NULL, *super = NULL;
|
||||||
mdp_super_t first_super, super;
|
|
||||||
struct {
|
struct {
|
||||||
char *devname;
|
char *devname;
|
||||||
unsigned int major, minor;
|
unsigned int major, minor;
|
||||||
unsigned int oldmajor, oldminor;
|
unsigned int oldmajor, oldminor;
|
||||||
long long events;
|
long long events;
|
||||||
time_t utime;
|
|
||||||
int uptodate;
|
int uptodate;
|
||||||
int state;
|
int state;
|
||||||
int raid_disk;
|
int raid_disk;
|
||||||
|
@ -119,6 +115,7 @@ int Assemble(char *mddev, int mdfd,
|
||||||
int start_partial_ok = force || devlist==NULL;
|
int start_partial_ok = force || devlist==NULL;
|
||||||
unsigned int num_devs;
|
unsigned int num_devs;
|
||||||
mddev_dev_t tmpdev;
|
mddev_dev_t tmpdev;
|
||||||
|
struct mdinfo info;
|
||||||
|
|
||||||
vers = md_get_version(mdfd);
|
vers = md_get_version(mdfd);
|
||||||
if (vers <= 0) {
|
if (vers <= 0) {
|
||||||
|
@ -133,7 +130,7 @@ int Assemble(char *mddev, int mdfd,
|
||||||
if (get_linux_version() < 2004000)
|
if (get_linux_version() < 2004000)
|
||||||
old_linux = 1;
|
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",
|
fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
|
||||||
mddev);
|
mddev);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -165,12 +162,8 @@ int Assemble(char *mddev, int mdfd,
|
||||||
num_devs++;
|
num_devs++;
|
||||||
tmpdev = tmpdev->next;
|
tmpdev = tmpdev->next;
|
||||||
}
|
}
|
||||||
best = malloc(num_devs * sizeof(*best));
|
|
||||||
devices = malloc(num_devs * sizeof(*devices));
|
devices = malloc(num_devs * sizeof(*devices));
|
||||||
|
|
||||||
first_super.md_magic = 0;
|
|
||||||
for (i=0; i<num_devs; i++)
|
|
||||||
best[i] = -1;
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, Name ": looking for devices for %s\n",
|
fprintf(stderr, Name ": looking for devices for %s\n",
|
||||||
|
@ -178,10 +171,8 @@ int Assemble(char *mddev, int mdfd,
|
||||||
|
|
||||||
while ( devlist) {
|
while ( devlist) {
|
||||||
char *devname;
|
char *devname;
|
||||||
int this_uuid[4];
|
|
||||||
int dfd;
|
int dfd;
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
int havesuper=0;
|
|
||||||
|
|
||||||
devname = devlist->devname;
|
devname = devlist->devname;
|
||||||
devlist = devlist->next;
|
devlist = devlist->next;
|
||||||
|
@ -193,6 +184,11 @@ int Assemble(char *mddev, int mdfd,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (super) {
|
||||||
|
free(super);
|
||||||
|
super = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dfd = open(devname, O_RDONLY|O_EXCL, 0);
|
dfd = open(devname, O_RDONLY|O_EXCL, 0);
|
||||||
if (dfd < 0) {
|
if (dfd < 0) {
|
||||||
if (inargv || verbose)
|
if (inargv || verbose)
|
||||||
|
@ -207,40 +203,39 @@ int Assemble(char *mddev, int mdfd,
|
||||||
fprintf(stderr, Name ": %s is not a block device.\n",
|
fprintf(stderr, Name ": %s is not a block device.\n",
|
||||||
devname);
|
devname);
|
||||||
close(dfd);
|
close(dfd);
|
||||||
} else if (load_super(dfd, &super)) {
|
} else if (load_super0(dfd, &super, NULL)) {
|
||||||
if (inargv || verbose)
|
if (inargv || verbose)
|
||||||
fprintf( stderr, Name ": no RAID superblock on %s\n",
|
fprintf( stderr, Name ": no RAID superblock on %s\n",
|
||||||
devname);
|
devname);
|
||||||
close(dfd);
|
close(dfd);
|
||||||
} else {
|
} else {
|
||||||
havesuper =1;
|
getinfo_super0(&info, super);
|
||||||
uuid_from_super(this_uuid, &super);
|
|
||||||
close(dfd);
|
close(dfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ident->uuid_set &&
|
if (ident->uuid_set &&
|
||||||
(!havesuper || same_uuid(this_uuid, ident->uuid)==0)) {
|
(!super || same_uuid(info.uuid, ident->uuid)==0)) {
|
||||||
if (inargv || verbose)
|
if (inargv || verbose)
|
||||||
fprintf(stderr, Name ": %s has wrong uuid.\n",
|
fprintf(stderr, Name ": %s has wrong uuid.\n",
|
||||||
devname);
|
devname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ident->super_minor != UnSet &&
|
if (ident->super_minor != UnSet &&
|
||||||
(!havesuper || ident->super_minor != super.md_minor)) {
|
(!super || ident->super_minor != info.array.md_minor)) {
|
||||||
if (inargv || verbose)
|
if (inargv || verbose)
|
||||||
fprintf(stderr, Name ": %s has wrong super-minor.\n",
|
fprintf(stderr, Name ": %s has wrong super-minor.\n",
|
||||||
devname);
|
devname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ident->level != UnSet &&
|
if (ident->level != UnSet &&
|
||||||
(!havesuper|| ident->level != (int)super.level)) {
|
(!super|| ident->level != info.array.level)) {
|
||||||
if (inargv || verbose)
|
if (inargv || verbose)
|
||||||
fprintf(stderr, Name ": %s has wrong raid level.\n",
|
fprintf(stderr, Name ": %s has wrong raid level.\n",
|
||||||
devname);
|
devname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ident->raid_disks != UnSet &&
|
if (ident->raid_disks != UnSet &&
|
||||||
(!havesuper || ident->raid_disks!= super.raid_disks)) {
|
(!super || ident->raid_disks!= info.array.raid_disks)) {
|
||||||
if (inargv || verbose)
|
if (inargv || verbose)
|
||||||
fprintf(stderr, Name ": %s requires wrong number of drives.\n",
|
fprintf(stderr, Name ": %s requires wrong number of drives.\n",
|
||||||
devname);
|
devname);
|
||||||
|
@ -252,85 +247,34 @@ int Assemble(char *mddev, int mdfd,
|
||||||
* then we cannot continue
|
* then we cannot continue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!havesuper) {
|
if (!super) {
|
||||||
fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
|
fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
|
||||||
devname);
|
devname);
|
||||||
|
free(first_super);
|
||||||
return 1;
|
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",
|
fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
|
||||||
devname);
|
devname);
|
||||||
|
free(super);
|
||||||
|
free(first_super);
|
||||||
return 1;
|
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 */
|
/* looks like a good enough match to update the super block if needed */
|
||||||
if (update) {
|
if (update) {
|
||||||
if (strcmp(update, "sparc2.2")==0 ) {
|
/* prepare useful information in info structures */
|
||||||
/* 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;
|
struct stat stb2;
|
||||||
fstat(mdfd, &stb2);
|
fstat(mdfd, &stb2);
|
||||||
super.md_minor = minor(stb2.st_rdev);
|
info.array.md_minor = minor(stb2.st_rdev);
|
||||||
if (verbose)
|
|
||||||
fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
|
update_super0(&info, super, update, devname, verbose);
|
||||||
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);
|
|
||||||
dfd = open(devname, O_RDWR|O_EXCL, 0);
|
dfd = open(devname, O_RDWR|O_EXCL, 0);
|
||||||
if (dfd < 0)
|
if (dfd < 0)
|
||||||
fprintf(stderr, Name ": Cannot open %s for superblock update\n",
|
fprintf(stderr, Name ": Cannot open %s for superblock update\n",
|
||||||
devname);
|
devname);
|
||||||
else if (store_super(dfd, &super))
|
else if (store_super0(dfd, super))
|
||||||
fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
|
fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
|
||||||
devname);
|
devname);
|
||||||
if (dfd >= 0)
|
if (dfd >= 0)
|
||||||
|
@ -339,23 +283,22 @@ int Assemble(char *mddev, int mdfd,
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
|
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].devname = devname;
|
||||||
devices[devcnt].major = major(stb.st_rdev);
|
devices[devcnt].major = major(stb.st_rdev);
|
||||||
devices[devcnt].minor = minor(stb.st_rdev);
|
devices[devcnt].minor = minor(stb.st_rdev);
|
||||||
devices[devcnt].oldmajor = super.this_disk.major;
|
devices[devcnt].oldmajor = info.disk.major;
|
||||||
devices[devcnt].oldminor = super.this_disk.minor;
|
devices[devcnt].oldminor = info.disk.minor;
|
||||||
devices[devcnt].events = md_event(&super);
|
devices[devcnt].events = info.events;
|
||||||
devices[devcnt].utime = super.utime;
|
devices[devcnt].raid_disk = info.disk.raid_disk;
|
||||||
devices[devcnt].raid_disk = super.this_disk.raid_disk;
|
|
||||||
devices[devcnt].uptodate = 0;
|
devices[devcnt].uptodate = 0;
|
||||||
devices[devcnt].state = super.this_disk.state;
|
devices[devcnt].state = info.disk.state;
|
||||||
if (most_recent < devcnt) {
|
if (most_recent < devcnt) {
|
||||||
if (devices[devcnt].events
|
if (devices[devcnt].events
|
||||||
> devices[most_recent].events)
|
> devices[most_recent].events)
|
||||||
most_recent = devcnt;
|
most_recent = devcnt;
|
||||||
}
|
}
|
||||||
if ((int)super.level == -4)
|
if (info.array.level == -4)
|
||||||
/* with multipath, the raid_disk from the superblock is meaningless */
|
/* with multipath, the raid_disk from the superblock is meaningless */
|
||||||
i = devcnt;
|
i = devcnt;
|
||||||
else
|
else
|
||||||
|
@ -381,11 +324,19 @@ int Assemble(char *mddev, int mdfd,
|
||||||
devcnt++;
|
devcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (super)
|
||||||
|
free(super);
|
||||||
|
super = NULL;
|
||||||
|
|
||||||
if (devcnt == 0) {
|
if (devcnt == 0) {
|
||||||
fprintf(stderr, Name ": no devices found for %s\n",
|
fprintf(stderr, Name ": no devices found for %s\n",
|
||||||
mddev);
|
mddev);
|
||||||
|
free(first_super);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getinfo_super0(&info, first_super);
|
||||||
|
|
||||||
/* now we have some devices that might be suitable.
|
/* now we have some devices that might be suitable.
|
||||||
* I wonder how many
|
* I wonder how many
|
||||||
*/
|
*/
|
||||||
|
@ -398,7 +349,7 @@ int Assemble(char *mddev, int mdfd,
|
||||||
/* note: we ignore error flags in multipath arrays
|
/* note: we ignore error flags in multipath arrays
|
||||||
* as they don't make sense
|
* 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_SYNC))) {
|
||||||
if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
|
if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
|
||||||
sparecnt++;
|
sparecnt++;
|
||||||
|
@ -407,20 +358,20 @@ int Assemble(char *mddev, int mdfd,
|
||||||
if (devices[j].events+event_margin >=
|
if (devices[j].events+event_margin >=
|
||||||
devices[most_recent].events) {
|
devices[most_recent].events) {
|
||||||
devices[j].uptodate = 1;
|
devices[j].uptodate = 1;
|
||||||
if (i < first_super.raid_disks)
|
if (i < info.array.raid_disks)
|
||||||
okcnt++;
|
okcnt++;
|
||||||
else
|
else
|
||||||
sparecnt++;
|
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
|
/* Choose the newest best drive which is
|
||||||
* not up-to-date, update the superblock
|
* not up-to-date, update the superblock
|
||||||
* and add it.
|
* and add it.
|
||||||
*/
|
*/
|
||||||
int fd;
|
int fd;
|
||||||
chosen_drive = -1;
|
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];
|
int j = best[i];
|
||||||
if (j>=0 &&
|
if (j>=0 &&
|
||||||
!devices[j].uptodate &&
|
!devices[j].uptodate &&
|
||||||
|
@ -442,31 +393,29 @@ int Assemble(char *mddev, int mdfd,
|
||||||
devices[chosen_drive].events = 0;
|
devices[chosen_drive].events = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (load_super(fd, &super)) {
|
if (load_super0(fd, &super, NULL)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
|
fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
|
||||||
devices[chosen_drive].devname);
|
devices[chosen_drive].devname);
|
||||||
devices[chosen_drive].events = 0;
|
devices[chosen_drive].events = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
super.events_hi = (devices[most_recent].events>>32)&0xFFFFFFFF;
|
info.events = devices[most_recent].events;
|
||||||
super.events_lo = (devices[most_recent].events)&0xFFFFFFFF;
|
update_super0(&info, super, "force", devices[chosen_drive].devname, verbose);
|
||||||
if (super.level == 5 || super.level == 4) {
|
|
||||||
/* need to force clean */
|
if (store_super0(fd, super)) {
|
||||||
super.state = (1<<MD_SB_CLEAN);
|
|
||||||
}
|
|
||||||
super.sb_csum = calc_sb_csum(&super);
|
|
||||||
/*DRYRUN*/ if (store_super(fd, &super)) {
|
|
||||||
close(fd);
|
close(fd);
|
||||||
fprintf(stderr, Name ": Could not re-write superblock on %s\n",
|
fprintf(stderr, Name ": Could not re-write superblock on %s\n",
|
||||||
devices[chosen_drive].devname);
|
devices[chosen_drive].devname);
|
||||||
devices[chosen_drive].events = 0;
|
devices[chosen_drive].events = 0;
|
||||||
|
free(super);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
devices[chosen_drive].events = devices[most_recent].events;
|
devices[chosen_drive].events = devices[most_recent].events;
|
||||||
devices[chosen_drive].uptodate = 1;
|
devices[chosen_drive].uptodate = 1;
|
||||||
okcnt++;
|
okcnt++;
|
||||||
|
free(super);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we want to look at the superblock which the kernel will base things on
|
/* 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.
|
* superblock.
|
||||||
*/
|
*/
|
||||||
chosen_drive = -1;
|
chosen_drive = -1;
|
||||||
|
super = NULL;
|
||||||
for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
|
for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
|
||||||
int j = best[i];
|
int j = best[i];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (j<0)
|
if (j<0)
|
||||||
continue;
|
continue;
|
||||||
if (!devices[j].uptodate)
|
if (!devices[j].uptodate)
|
||||||
|
@ -489,7 +440,7 @@ int Assemble(char *mddev, int mdfd,
|
||||||
devices[j].devname, strerror(errno));
|
devices[j].devname, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (load_super(fd, &super)) {
|
if (load_super0(fd, &super, NULL)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
|
fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
|
||||||
devices[j].devname);
|
devices[j].devname);
|
||||||
|
@ -497,12 +448,16 @@ int Assemble(char *mddev, int mdfd,
|
||||||
}
|
}
|
||||||
close(fd);
|
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++) {
|
for (i=0; i<bestcnt; i++) {
|
||||||
int j = best[i];
|
int j = best[i];
|
||||||
unsigned int desired_state;
|
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);
|
desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
|
||||||
else
|
else
|
||||||
desired_state = 0;
|
desired_state = 0;
|
||||||
|
@ -511,77 +466,57 @@ int Assemble(char *mddev, int mdfd,
|
||||||
continue;
|
continue;
|
||||||
if (!devices[j].uptodate)
|
if (!devices[j].uptodate)
|
||||||
continue;
|
continue;
|
||||||
#if 0
|
info.disk.number = i;
|
||||||
This doesnt work yet
|
info.disk.state = desired_state;
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (devices[j].uptodate &&
|
if (devices[j].uptodate &&
|
||||||
(super.disks[i].state != desired_state)) {
|
update_super0(&info, super, "assemble", NULL, 0)) {
|
||||||
if (force) {
|
if (force) {
|
||||||
fprintf(stderr, Name ": "
|
fprintf(stderr, Name ": "
|
||||||
"clearing FAULTY flag for device %d in %s for %s\n",
|
"clearing FAULTY flag for device %d in %s for %s\n",
|
||||||
j, mddev, devices[j].devname);
|
j, mddev, devices[j].devname);
|
||||||
super.disks[i].state = desired_state;
|
change = 1;
|
||||||
change |= 2;
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, Name ": "
|
fprintf(stderr, Name ": "
|
||||||
"device %d in %s has wrong state in superblock, but %s seems ok\n",
|
"device %d in %s has wrong state in superblock, but %s seems ok\n",
|
||||||
i, mddev, devices[j].devname);
|
i, mddev, devices[j].devname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
if (!devices[j].uptodate &&
|
if (!devices[j].uptodate &&
|
||||||
!(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
|
!(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",
|
fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
|
||||||
i, mddev);
|
i, mddev);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (force && (super.level == 4 || super.level == 5) &&
|
if (force && okcnt == info.array.raid_disks-1) {
|
||||||
okcnt == super.raid_disks-1) {
|
/* FIXME check event count */
|
||||||
super.state = (1<< MD_SB_CLEAN);
|
change += update_super0(&info, super, "force",
|
||||||
change |= 2;
|
devices[chosen_drive].devname, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((force && (change & 2))
|
if (change) {
|
||||||
|| (old_linux && (change & 1))) {
|
|
||||||
int fd;
|
int fd;
|
||||||
super.sb_csum = calc_sb_csum(&super);
|
|
||||||
fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
|
fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, Name ": Could open %s for write - cannot Assemble array.\n",
|
fprintf(stderr, Name ": Could open %s for write - cannot Assemble array.\n",
|
||||||
devices[chosen_drive].devname);
|
devices[chosen_drive].devname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (store_super(fd, &super)) {
|
if (store_super0(fd, super)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
fprintf(stderr, Name ": Could not re-write superblock on %s\n",
|
fprintf(stderr, Name ": Could not re-write superblock on %s\n",
|
||||||
devices[chosen_drive].devname);
|
devices[chosen_drive].devname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
change = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count number of in-sync devices according to the superblock.
|
/* count number of in-sync devices according to the superblock.
|
||||||
* We must have this number to start the array without -s or -R
|
* We must have this number to start the array without -s or -R
|
||||||
*/
|
*/
|
||||||
req_cnt = 0;
|
req_cnt = info.array.working_disks;
|
||||||
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 ++;
|
|
||||||
|
|
||||||
|
|
||||||
/* Almost ready to actually *do* something */
|
/* Almost ready to actually *do* something */
|
||||||
if (!old_linux) {
|
if (!old_linux) {
|
||||||
|
@ -610,28 +545,28 @@ This doesnt work yet
|
||||||
devices[j].devname,
|
devices[j].devname,
|
||||||
mddev,
|
mddev,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
if (i < first_super.raid_disks || i == bestcnt)
|
if (i < info.array.raid_disks || i == bestcnt)
|
||||||
okcnt--;
|
okcnt--;
|
||||||
else
|
else
|
||||||
sparecnt--;
|
sparecnt--;
|
||||||
} else if (verbose)
|
} else if (verbose)
|
||||||
fprintf(stderr, Name ": added %s to %s as %d\n",
|
fprintf(stderr, Name ": added %s to %s as %d\n",
|
||||||
devices[j].devname, mddev, devices[j].raid_disk);
|
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",
|
fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
|
||||||
i, mddev);
|
i, mddev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runstop == 1 ||
|
if (runstop == 1 ||
|
||||||
(runstop == 0 &&
|
(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)
|
(okcnt >= req_cnt || start_partial_ok)
|
||||||
))) {
|
))) {
|
||||||
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
|
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
|
||||||
fprintf(stderr, Name ": %s has been started with %d drive%s",
|
fprintf(stderr, Name ": %s has been started with %d drive%s",
|
||||||
mddev, okcnt, okcnt==1?"":"s");
|
mddev, okcnt, okcnt==1?"":"s");
|
||||||
if (okcnt < first_super.raid_disks)
|
if (okcnt < info.array.raid_disks)
|
||||||
fprintf(stderr, " (out of %d)", first_super.raid_disks);
|
fprintf(stderr, " (out of %d)", info.array.raid_disks);
|
||||||
if (sparecnt)
|
if (sparecnt)
|
||||||
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
|
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
|
||||||
fprintf(stderr, ".\n");
|
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");
|
fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
|
||||||
if (sparecnt)
|
if (sparecnt)
|
||||||
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
|
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");
|
fprintf(stderr, " - not enough to start the array.\n");
|
||||||
else {
|
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);
|
fprintf(stderr, " - need all %d to start it", req_cnt);
|
||||||
else
|
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");
|
fprintf(stderr, " (use --run to insist).\n");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
27
Create.c
27
Create.c
|
@ -62,7 +62,8 @@ int Create(char *mddev, int mdfd,
|
||||||
int first_missing = MD_SB_DISKS*2;
|
int first_missing = MD_SB_DISKS*2;
|
||||||
int missing_disks = 0;
|
int missing_disks = 0;
|
||||||
int insert_point = MD_SB_DISKS*2; /* where to insert a missing drive */
|
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;
|
mdu_array_info_t array;
|
||||||
|
|
||||||
|
@ -342,13 +343,20 @@ int Create(char *mddev, int mdfd,
|
||||||
array.layout = layout;
|
array.layout = layout;
|
||||||
array.chunk_size = chunk*1024;
|
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",
|
fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
|
||||||
mddev, strerror(errno));
|
mddev, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dnum=0, dv = devlist ; dv ; dv=(dv->next)?(dv->next):moved_disk, dnum++) {
|
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;
|
int fd;
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
mdu_disk_info_t disk;
|
mdu_disk_info_t disk;
|
||||||
|
@ -379,13 +387,26 @@ int Create(char *mddev, int mdfd,
|
||||||
disk.minor = minor(stb.st_rdev);
|
disk.minor = minor(stb.st_rdev);
|
||||||
close(fd);
|
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)) {
|
if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
|
||||||
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
|
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
|
||||||
dv->devname, strerror(errno));
|
dv->devname, strerror(errno));
|
||||||
|
free(super);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (dv == moved_disk && dnum != insert_point) break;
|
if (dv == moved_disk && dnum != insert_point) break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
free(super);
|
||||||
|
|
||||||
/* param is not actually used */
|
/* param is not actually used */
|
||||||
if (runstop == 1 || subdevs >= raiddisks) {
|
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 is_rebuilding = 0;
|
||||||
int failed = 0;
|
int failed = 0;
|
||||||
|
|
||||||
mdp_super_t super;
|
void *super = NULL;
|
||||||
int have_super = 0;
|
|
||||||
int rv = test ? 4 : 1;
|
int rv = test ? 4 : 1;
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -99,16 +98,21 @@ int Detail(char *dev, int brief, int test)
|
||||||
disk.minor == 0)
|
disk.minor == 0)
|
||||||
continue;
|
continue;
|
||||||
if ((dv=map_dev(disk.major, disk.minor))) {
|
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
|
/* try to read the superblock from this device
|
||||||
* to get more info
|
* to get more info
|
||||||
*/
|
*/
|
||||||
int fd2 = open(dv, O_RDONLY);
|
int fd2 = open(dv, O_RDONLY);
|
||||||
if (fd2 >=0 &&
|
if (fd2 >=0 &&
|
||||||
load_super(fd2, &super) ==0 &&
|
load_super0(fd2, &super, NULL) == 0) {
|
||||||
(unsigned long)super.ctime == (unsigned long)array.ctime &&
|
struct mdinfo info;
|
||||||
(unsigned int)super.level == (unsigned int)array.level)
|
getinfo_super0(&info, super);
|
||||||
have_super = 1;
|
if (info.array.ctime != array.ctime ||
|
||||||
|
info.array.level != array.level) {
|
||||||
|
free(super);
|
||||||
|
super = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fd2 >= 0) close(fd2);
|
if (fd2 >= 0) close(fd2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,15 +202,8 @@ int Detail(char *dev, int brief, int test)
|
||||||
}
|
}
|
||||||
free_mdstat(ms);
|
free_mdstat(ms);
|
||||||
|
|
||||||
if (have_super) {
|
if (super)
|
||||||
printf(" UUID : ");
|
detail_super0(super);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(" Number Major Minor RaidDevice State\n");
|
printf(" Number Major Minor RaidDevice State\n");
|
||||||
}
|
}
|
||||||
|
@ -278,14 +275,9 @@ int Detail(char *dev, int brief, int test)
|
||||||
if (!brief) printf("\n");
|
if (!brief) printf("\n");
|
||||||
}
|
}
|
||||||
if (spares && brief) printf(" spares=%d", spares);
|
if (spares && brief) printf(" spares=%d", spares);
|
||||||
if (have_super && brief) {
|
if (super && brief)
|
||||||
printf(" UUID=");
|
brief_detail_super0(super);
|
||||||
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 (brief && devices) printf("\n devices=%s", devices);
|
if (brief && devices) printf("\n devices=%s", devices);
|
||||||
if (brief) printf("\n");
|
if (brief) printf("\n");
|
||||||
if (test && (rv&2)) rv &= ~1;
|
if (test && (rv&2)) rv &= ~1;
|
||||||
|
|
178
Examine.c
178
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(
|
* if devlist==NULL, use conf_get_devs(
|
||||||
*/
|
*/
|
||||||
int fd;
|
int fd;
|
||||||
time_t atime;
|
void *super = NULL;
|
||||||
mdp_super_t super;
|
|
||||||
int d;
|
|
||||||
char *c;
|
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
int err;
|
int err;
|
||||||
int spares = 0;
|
|
||||||
|
|
||||||
struct array {
|
struct array {
|
||||||
mdp_super_t super;
|
void *super;
|
||||||
|
struct mdinfo info;
|
||||||
void *devs;
|
void *devs;
|
||||||
struct array *next;
|
struct array *next;
|
||||||
|
int spares;
|
||||||
} *arrays = NULL;
|
} *arrays = NULL;
|
||||||
|
|
||||||
for (; devlist ; devlist=devlist->next) {
|
for (; devlist ; devlist=devlist->next) {
|
||||||
|
@ -77,48 +75,21 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
|
||||||
err = 1;
|
err = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
err = load_super(fd, &super);
|
err = load_super0(fd, &super, (brief||scan)?NULL:devlist->devname);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
if (err && (brief||scan))
|
if (err)
|
||||||
continue;
|
continue;
|
||||||
if (err) rv =1;
|
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 */
|
/* Ok, its good enough to try, though the checksum could be wrong */
|
||||||
if (brief) {
|
if (brief) {
|
||||||
struct array *ap;
|
struct array *ap;
|
||||||
char *d;
|
char *d;
|
||||||
for (ap=arrays; ap; ap=ap->next) {
|
for (ap=arrays; ap; ap=ap->next) {
|
||||||
if (compare_super(&ap->super, &super)==0)
|
if (compare_super0(&ap->super, super)==0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!ap) {
|
if (!ap) {
|
||||||
|
@ -126,140 +97,37 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
|
||||||
ap->super = super;
|
ap->super = super;
|
||||||
ap->devs = dl_head();
|
ap->devs = dl_head();
|
||||||
ap->next = arrays;
|
ap->next = arrays;
|
||||||
|
ap->spares = 0;
|
||||||
arrays = ap;
|
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);
|
d = dl_strdup(devlist->devname);
|
||||||
dl_add(ap->devs, d);
|
dl_add(ap->devs, d);
|
||||||
} else {
|
} else {
|
||||||
printf("%s:\n",devlist->devname);
|
printf("%s:\n",devlist->devname);
|
||||||
printf(" Magic : %08x\n", super.md_magic);
|
examine_super0(super);
|
||||||
printf(" Version : %02d.%02d.%02d\n", super.major_version, super.minor_version,
|
free(super);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (brief) {
|
if (brief) {
|
||||||
struct array *ap;
|
struct array *ap;
|
||||||
for (ap=arrays; ap; ap=ap->next) {
|
for (ap=arrays; ap; ap=ap->next) {
|
||||||
char sep='=';
|
char sep='=';
|
||||||
char *c=map_num(pers, ap->super.level);
|
|
||||||
char *d;
|
char *d;
|
||||||
printf("ARRAY %s level=%s num-devices=%d UUID=",
|
brief_examine_super0(ap->super);
|
||||||
get_md_name(ap->super.md_minor),
|
if (ap->spares) printf(" spares=%d", ap->spares);
|
||||||
c?c:"-unknown-", ap->super.raid_disks);
|
printf(" devices");
|
||||||
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");
|
|
||||||
for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
|
for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
|
||||||
printf("%c%s", sep, d);
|
printf("%c%s", sep, d);
|
||||||
sep=',';
|
sep=',';
|
||||||
}
|
}
|
||||||
|
free(ap->super);
|
||||||
|
/* FIXME free ap */
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
70
Grow.c
70
Grow.c
|
@ -45,20 +45,20 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
||||||
* all other devices.
|
* all other devices.
|
||||||
* This means that we need to *find* all other devices.
|
* This means that we need to *find* all other devices.
|
||||||
*/
|
*/
|
||||||
mdu_array_info_t array;
|
struct mdinfo info;
|
||||||
mdu_disk_info_t disk;
|
|
||||||
mdp_super_t super;
|
void *super = NULL;
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
int nfd, fd2;
|
int nfd, fd2;
|
||||||
int d, nd;
|
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);
|
fprintf(stderr, Name ": cannot get array info for %s\n", devname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array.level != -1) {
|
if (info.array.level != -1) {
|
||||||
fprintf(stderr, Name ": can only add devices to linear arrays\n");
|
fprintf(stderr, Name ": can only add devices to linear arrays\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* now check out all the devices and make sure we can read the superblock */
|
/* 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;
|
mdu_disk_info_t disk;
|
||||||
char *dv;
|
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);
|
fprintf(stderr, Name ": cannot open device file %s\n", dv);
|
||||||
return 1;
|
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);
|
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
|
||||||
close(fd2);
|
close(fd2);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -107,27 +109,21 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
||||||
* newdev.
|
* newdev.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(&super.disks[d], 0, sizeof(super.disks[d]));
|
info.disk.number = d;
|
||||||
super.disks[d].number = d;
|
info.disk.major = major(stb.st_rdev);
|
||||||
super.disks[d].major = major(stb.st_rdev);
|
info.disk.minor = minor(stb.st_rdev);
|
||||||
super.disks[d].minor = minor(stb.st_rdev);
|
info.disk.raid_disk = d;
|
||||||
super.disks[d].raid_disk = d;
|
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
||||||
super.disks[d].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
update_super0(&info, super, "grow", newdev, 0);
|
||||||
|
|
||||||
super.this_disk = super.disks[d];
|
if (store_super0(nfd, super)) {
|
||||||
super.sb_csum = calc_sb_csum(&super);
|
|
||||||
if (store_super(nfd, &super)) {
|
|
||||||
fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
|
fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
|
||||||
close(nfd);
|
close(nfd);
|
||||||
return 1;
|
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);
|
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");
|
fprintf(stderr, Name ": Cannot add new disk to this array\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -135,13 +131,13 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
||||||
* Now go through and update all superblocks
|
* 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);
|
fprintf(stderr, Name ": cannot get array info for %s\n", devname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nd = d;
|
nd = d;
|
||||||
for (d=0 ; d < array.raid_disks ; d++) {
|
for (d=0 ; d < info.array.raid_disks ; d++) {
|
||||||
mdu_disk_info_t disk;
|
mdu_disk_info_t disk;
|
||||||
char *dv;
|
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);
|
fprintf(stderr, Name ": cannot open device file %s\n", dv);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (load_super(fd2, &super)) {
|
if (load_super0(fd2, &super, NULL)) {
|
||||||
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
|
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
|
||||||
close(fd);
|
close(fd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
super.raid_disks = nd+1;
|
info.array.raid_disks = nd+1;
|
||||||
super.nr_disks = nd+1;
|
info.array.nr_disks = nd+1;
|
||||||
super.active_disks = nd+1;
|
info.array.active_disks = nd+1;
|
||||||
super.working_disks = nd+1;
|
info.array.working_disks = nd+1;
|
||||||
memset(&super.disks[nd], 0, sizeof(super.disks[nd]));
|
info.disk.number = nd;
|
||||||
super.disks[nd].number = nd;
|
info.disk.major = major(stb.st_rdev);
|
||||||
super.disks[nd].major = major(stb.st_rdev);
|
info.disk.minor = minor(stb.st_rdev);
|
||||||
super.disks[nd].minor = minor(stb.st_rdev);
|
info.disk.raid_disk = nd;
|
||||||
super.disks[nd].raid_disk = nd;
|
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
||||||
super.disks[nd].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
update_super0(&info, super, "grow", dv, 0);
|
||||||
|
|
||||||
super.this_disk = super.disks[d];
|
if (store_super0(fd2, super)) {
|
||||||
super.sb_csum = calc_sb_csum(&super);
|
|
||||||
if (store_super(fd2, &super)) {
|
|
||||||
fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
|
fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
|
||||||
close(fd2);
|
close(fd2);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
30
Kill.c
30
Kill.c
|
@ -41,7 +41,7 @@ int Kill(char *dev, int force)
|
||||||
* Definitely not safe.
|
* Definitely not safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mdp_super_t super;
|
void *super;
|
||||||
int fd, rv = 0;
|
int fd, rv = 0;
|
||||||
|
|
||||||
fd = open(dev, O_RDWR|O_EXCL);
|
fd = open(dev, O_RDWR|O_EXCL);
|
||||||
|
@ -50,32 +50,18 @@ int Kill(char *dev, int force)
|
||||||
dev);
|
dev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
rv = load_super(fd, &super);
|
rv = load_super0(fd, &super, dev);
|
||||||
if (force && rv >= 5)
|
if (force && rv >= 2)
|
||||||
rv = 0; /* ignore bad data in superblock */
|
rv = 0; /* ignore bad data in superblock */
|
||||||
switch(rv) {
|
if (rv== 0 || (force && rv >= 2)) {
|
||||||
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) {
|
|
||||||
memset(&super, 0, sizeof(super));
|
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",
|
fprintf(stderr, Name ": Could not zero superblock on %s\n",
|
||||||
dev);
|
dev);
|
||||||
rv = 1;
|
rv = 1;
|
||||||
|
} else if (rv) {
|
||||||
|
fprintf(stderr, Name ": superblock zeroed anyway\n");
|
||||||
|
rv = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -58,9 +58,10 @@ MAN5DIR = $(MANDIR)/man5
|
||||||
MAN8DIR = $(MANDIR)/man8
|
MAN8DIR = $(MANDIR)/man8
|
||||||
|
|
||||||
OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o \
|
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 \
|
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
|
ASSEMBLE_SRCS := mdassemble.c Assemble.c config.c dlink.c util.c
|
||||||
ifdef MDASSEMBLE_AUTO
|
ifdef MDASSEMBLE_AUTO
|
||||||
ASSEMBLE_SRCS += mdopen.c mdstat.c
|
ASSEMBLE_SRCS += mdopen.c mdstat.c
|
||||||
|
|
49
Query.c
49
Query.c
|
@ -41,8 +41,10 @@ int Query(char *dev)
|
||||||
int vers;
|
int vers;
|
||||||
int ioctlerr;
|
int ioctlerr;
|
||||||
int superror, superrno;
|
int superror, superrno;
|
||||||
mdp_super_t super;
|
struct mdinfo info;
|
||||||
mdu_array_info_t array;
|
mdu_array_info_t array;
|
||||||
|
void *super;
|
||||||
|
|
||||||
unsigned long long larray_size;
|
unsigned long long larray_size;
|
||||||
unsigned long array_size;
|
unsigned long array_size;
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
|
@ -60,8 +62,6 @@ int Query(char *dev)
|
||||||
if (ioctl(fd, GET_ARRAY_INFO, &array)<0)
|
if (ioctl(fd, GET_ARRAY_INFO, &array)<0)
|
||||||
ioctlerr = errno;
|
ioctlerr = errno;
|
||||||
else ioctlerr = 0;
|
else ioctlerr = 0;
|
||||||
superror = load_super(fd, &super);
|
|
||||||
superrno = errno;
|
|
||||||
|
|
||||||
fstat(fd, &stb);
|
fstat(fd, &stb);
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@ int Query(char *dev)
|
||||||
larray_size <<= 9;
|
larray_size <<= 9;
|
||||||
} else larray_size = 0;
|
} else larray_size = 0;
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (vers < 0)
|
if (vers < 0)
|
||||||
printf("%s: is not an md array\n", dev);
|
printf("%s: is not an md array\n", dev);
|
||||||
|
@ -95,35 +94,14 @@ int Query(char *dev)
|
||||||
array.raid_disks,
|
array.raid_disks,
|
||||||
array.spare_disks, array.spare_disks==1?"":"s");
|
array.spare_disks, array.spare_disks==1?"":"s");
|
||||||
}
|
}
|
||||||
switch(superror) {
|
superror = load_super0(fd, &super, dev);
|
||||||
case 1:
|
superrno = errno;
|
||||||
printf("%s: cannot find device size: %s\n",
|
close(fd);
|
||||||
dev, strerror(superrno));
|
if (superror == 0) {
|
||||||
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:
|
|
||||||
/* array might be active... */
|
/* array might be active... */
|
||||||
mddev = get_md_name(super.md_minor);
|
getinfo_super0(&info, super);
|
||||||
disc.number = super.this_disk.number;
|
mddev = get_md_name(info.array.md_minor);
|
||||||
|
disc.number = info.disk.number;
|
||||||
activity = "undetected";
|
activity = "undetected";
|
||||||
if (mddev && (fd = open(mddev, O_RDONLY))>=0) {
|
if (mddev && (fd = open(mddev, O_RDONLY))>=0) {
|
||||||
if (md_get_version(fd) >= 9000 &&
|
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",
|
printf("%s: device %d in %d device %s %s md%d. Use mdadm --examine for more detail.\n",
|
||||||
dev,
|
dev,
|
||||||
super.this_disk.number, super.raid_disks,
|
info.disk.number, info.array.raid_disks,
|
||||||
activity,
|
activity,
|
||||||
map_num(pers, super.level),
|
map_num(pers, info.array.level),
|
||||||
super.md_minor);
|
info.array.md_minor);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
1
ReadMe.c
1
ReadMe.c
|
@ -30,6 +30,7 @@
|
||||||
#include "mdadm.h"
|
#include "mdadm.h"
|
||||||
|
|
||||||
char Version[] = Name " - v1.11.0 - 11 April 2005\n";
|
char Version[] = Name " - v1.11.0 - 11 April 2005\n";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File: ReadMe.c
|
* 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_u.h"
|
||||||
#include "md_p.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"
|
#define Name "mdadm"
|
||||||
|
|
||||||
enum mode {
|
enum mode {
|
||||||
|
@ -211,11 +219,10 @@ extern char *conf_line(FILE *file);
|
||||||
extern char *conf_word(FILE *file, int allow_key);
|
extern char *conf_word(FILE *file, int allow_key);
|
||||||
extern void free_line(char *line);
|
extern void free_line(char *line);
|
||||||
extern int match_oneof(char *devices, char *devname);
|
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 void uuid_from_super(int uuid[4], mdp_super_t *super);
|
||||||
extern int same_uuid(int a[4], int b[4]);
|
extern int same_uuid(int a[4], int b[4]);
|
||||||
extern int compare_super(mdp_super_t *first, mdp_super_t *second);
|
/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
|
||||||
extern unsigned long calc_sb_csum(mdp_super_t *super);
|
extern unsigned long calc_csum(void *super, int bytes);
|
||||||
extern int store_super(int fd, mdp_super_t *super);
|
extern int store_super(int fd, mdp_super_t *super);
|
||||||
extern int enough(int level, int raid_disks, int avail_disks);
|
extern int enough(int level, int raid_disks, int avail_disks);
|
||||||
extern int ask(char *mesg);
|
extern int ask(char *mesg);
|
||||||
|
@ -255,3 +262,18 @@ extern int open_mddev(char *dev, int autof);
|
||||||
|
|
||||||
#define ModeMask 0x1f
|
#define ModeMask 0x1f
|
||||||
#define ModeShift 5
|
#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;
|
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)
|
int check_ext2(int fd, char *name)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -339,18 +205,25 @@ int check_reiser(int fd, char *name)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int load_super(int fd, void **sbp, int vers)
|
||||||
|
{
|
||||||
|
return load_super0(fd, sbp, NULL);
|
||||||
|
}
|
||||||
int check_raid(int fd, char *name)
|
int check_raid(int fd, char *name)
|
||||||
{
|
{
|
||||||
mdp_super_t super;
|
void *super;
|
||||||
|
struct mdinfo info;
|
||||||
time_t crtime;
|
time_t crtime;
|
||||||
if (load_super(fd, &super))
|
if (load_super(fd, &super, -1))
|
||||||
return 0;
|
return 0;
|
||||||
/* Looks like a raid array .. */
|
/* Looks like a raid array .. */
|
||||||
fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
|
fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
|
||||||
name);
|
name);
|
||||||
crtime = super.ctime;
|
getinfo_super0(&info, super);
|
||||||
|
free(super);
|
||||||
|
crtime = info.array.ctime;
|
||||||
fprintf(stderr, " level=%d devices=%d ctime=%s",
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,19 +379,16 @@ char *map_dev(int major, int minor)
|
||||||
|
|
||||||
#endif
|
#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 long newcsum = 0;
|
||||||
unsigned long csum;
|
|
||||||
int i;
|
int i;
|
||||||
unsigned int *superc = (int*) super;
|
unsigned int csum;
|
||||||
super->sb_csum = 0;
|
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];
|
newcsum+= superc[i];
|
||||||
csum = (newcsum& 0xffffffff) + (newcsum>>32);
|
csum = (newcsum& 0xffffffff) + (newcsum>>32);
|
||||||
super->sb_csum = oldcsum;
|
|
||||||
return csum;
|
return csum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue