summaryrefslogtreecommitdiffstats
path: root/Assemble.c
diff options
context:
space:
mode:
Diffstat (limited to 'Assemble.c')
-rw-r--r--Assemble.c78
1 files changed, 67 insertions, 11 deletions
diff --git a/Assemble.c b/Assemble.c
index 7868802..a2ff502 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -35,6 +35,7 @@ int Assemble(char *mddev, int mdfd,
mddev_ident_t ident, char *conffile,
mddev_dev_t devlist,
int readonly, int runstop,
+ char *update,
int verbose, int force)
{
/*
@@ -72,7 +73,7 @@ int Assemble(char *mddev, int mdfd,
* For each device:
* 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 superbloc - discard if different
+ * Check superblock similarity if we have a superblock - discard if different
* Record events, devicenum, utime
* This should give us a list of devices for the array
* We should collect the most recent event and utime numbers
@@ -103,8 +104,8 @@ int Assemble(char *mddev, int mdfd,
time_t utime;
int uptodate;
int raid_disk;
- } devices[MD_SB_DISKS];
- int best[MD_SB_DISKS]; /* indexed by raid_disk */
+ } *devices;
+ int *best; /* indexed by raid_disk */
int devcnt = 0, okcnt, sparecnt;
int i;
int most_recent = 0;
@@ -112,6 +113,8 @@ int Assemble(char *mddev, int mdfd,
int change = 0;
int inargv = 0;
int start_partial_ok = force || devlist==NULL;
+ int num_devs;
+ mddev_dev_t tmpdev;
vers = md_get_version(mdfd);
if (vers <= 0) {
@@ -153,8 +156,16 @@ int Assemble(char *mddev, int mdfd,
devlist = conf_get_devs(conffile);
else inargv = 1;
+ tmpdev = devlist; num_devs = 0;
+ while (tmpdev) {
+ 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<MD_SB_DISKS; i++)
+ for (i=0; i<num_devs; i++)
best[i] = -1;
if (verbose)
@@ -245,11 +256,48 @@ int Assemble(char *mddev, int mdfd,
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);
+ }
+ super.sb_csum = calc_sb_csum(&super);
+ dfd = open(devname, O_RDWR, 0);
+ if (dfd < 0)
+ fprintf(stderr, Name ": Cannot open %s for superblock update\n",
+ devname);
+ else if (store_super(dfd, &super))
+ fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
+ devname);
+ if (dfd >= 0)
+ close(dfd);
+ }
+
if (verbose)
fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
devname, mddev, super.this_disk.raid_disk);
@@ -267,8 +315,12 @@ int Assemble(char *mddev, int mdfd,
> devices[most_recent].events)
most_recent = devcnt;
}
- i = devices[devcnt].raid_disk;
- if (i>=0 && i < MD_SB_DISKS)
+ if (super.level == -4)
+ /* with multipath, the raid_disk from the superblock is meaningless */
+ i = devcnt;
+ else
+ i = devices[devcnt].raid_disk;
+ if (i>=0 && i < num_devs)
if (best[i] == -1
|| devices[best[i]].events < devices[devcnt].events)
best[i] = devcnt;
@@ -286,7 +338,7 @@ int Assemble(char *mddev, int mdfd,
*/
okcnt = 0;
sparecnt=0;
- for (i=0; i< MD_SB_DISKS;i++) {
+ for (i=0; i< num_devs ;i++) {
int j = best[i];
int event_margin = !force;
if (j < 0) continue;
@@ -337,6 +389,10 @@ int Assemble(char *mddev, int mdfd,
}
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 = 0;
+ }
super.sb_csum = calc_sb_csum(&super);
/*DRYRUN*/ if (store_super(fd, &super)) {
close(fd);
@@ -358,7 +414,7 @@ int Assemble(char *mddev, int mdfd,
* superblock.
*/
chosen_drive = -1;
- for (i=0; chosen_drive < 0 && i<MD_SB_DISKS; i++) {
+ for (i=0; chosen_drive < 0 && i<num_devs; i++) {
int j = best[i];
int fd;
if (j<0)
@@ -380,7 +436,7 @@ int Assemble(char *mddev, int mdfd,
close(fd);
}
- for (i=0; i<MD_SB_DISKS; i++) {
+ for (i=0; i<num_devs; i++) {
int j = best[i];
int desired_state;
@@ -457,9 +513,9 @@ This doesnt work yet
return 1;
}
/* First, add the raid disks, but add the chosen one last */
- for (i=0; i<=MD_SB_DISKS; i++) {
+ for (i=0; i<= num_devs; i++) {
int j;
- if (i < MD_SB_DISKS) {
+ if (i < num_devs) {
j = best[i];
if (j == chosen_drive)
continue;