summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Assemble.c241
-rw-r--r--Create.c95
-rw-r--r--Detail.c40
-rw-r--r--Examine.c180
-rw-r--r--Grow.c72
-rw-r--r--Kill.c30
-rw-r--r--Makefile5
-rw-r--r--Query.c49
-rw-r--r--ReadMe.c1
-rw-r--r--mdadm.h28
-rw-r--r--super0.c539
-rw-r--r--util.c160
12 files changed, 823 insertions, 617 deletions
diff --git a/Assemble.c b/Assemble.c
index ace5717..e762c69 100644
--- a/Assemble.c
+++ b/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;
diff --git a/Create.c b/Create.c
index 66a88d2..87a275e 100644
--- a/Create.c
+++ b/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);
- }
- if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
- fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
- dv->devname, strerror(errno));
- return 1;
+ 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 (dv == moved_disk && dnum != insert_point) break;
}
+ free(super);
/* param is not actually used */
if (runstop == 1 || subdevs >= raiddisks) {
diff --git a/Detail.c b/Detail.c
index 7555a9a..59b091f 100644
--- a/Detail.c
+++ b/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;
diff --git a/Examine.c b/Examine.c
index 79537fa..cd79583 100644
--- a/Examine.c
+++ b/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");
}
}
diff --git a/Grow.c b/Grow.c
index 3f8a1c6..8de28d4 100644
--- a/Grow.c
+++ b/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;
diff --git a/Kill.c b/Kill.c
index 9441f73..fbda686 100644
--- a/Kill.c
+++ b/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);
diff --git a/Makefile b/Makefile
index 8f0547b..38cfcde 100644
--- a/Makefile
+++ b/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
diff --git a/Query.c b/Query.c
index 95d6914..71aafd8 100644
--- a/Query.c
+++ b/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;
}
diff --git a/ReadMe.c b/ReadMe.c
index 78073df..00283e9 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -30,6 +30,7 @@
#include "mdadm.h"
char Version[] = Name " - v1.11.0 - 11 April 2005\n";
+
/*
* File: ReadMe.c
*
diff --git a/mdadm.h b/mdadm.h
index b7f34d1..6638a34 100644
--- a/mdadm.h
+++ b/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);
diff --git a/super0.c b/super0.c
new file mode 100644
index 0000000..a65d1e1
--- /dev/null
+++ b/super0.c
@@ -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;
+}
diff --git a/util.c b/util.c
index d5e2910..e9bce2a 100644
--- a/util.c
+++ b/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;
}