summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-09-18 16:03:05 +1000
committerNeilBrown <neilb@suse.de>2008-09-18 16:03:05 +1000
commitc5afc314e2c36d54bf78b0d0049995c0f2df821c (patch)
treea154a2a3463b03b057f751b2592c7dfc81670c6f
parent352452c3648f683d5ee60c62ab243c37af87ada1 (diff)
Lots of fixes to make incremental assembly of containers work.
So: mdadm -I /dev/whatever will (if appropriate) add whatever to a container, then start any arrays inside the container.
-rw-r--r--Incremental.c149
-rw-r--r--mapfile.c8
-rw-r--r--mdopen.c2
-rw-r--r--super-ddf.c36
-rw-r--r--super-intel.c1
5 files changed, 121 insertions, 75 deletions
diff --git a/Incremental.c b/Incremental.c
index 5965dd1f..d7eeafc1 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -241,6 +241,8 @@ int Incremental(char *devname, int verbose, int runstop,
int use_partitions = 1;
char *np, *ep;
char *nm, nbuf[1024];
+ struct stat stb2;
+
if ((autof&7) == 3 || (autof&7) == 5)
use_partitions = 0;
if (st->ss->external)
@@ -264,14 +266,14 @@ int Incremental(char *devname, int verbose, int runstop,
sprintf(nbuf, "/dev/md/%s", np);
nm = nbuf;
}
- if (stat(nm, &stb) == 0 &&
- S_ISBLK(stb.st_mode) &&
- major(stb.st_rdev) == (use_partitions ?
- get_mdp_major() : MD_MAJOR)) {
+ if (stat(nm, &stb2) == 0 &&
+ S_ISBLK(stb2.st_mode) &&
+ major(stb2.st_rdev) == (use_partitions ?
+ get_mdp_major() : MD_MAJOR)) {
if (use_partitions)
- devnum = minor(stb.st_rdev) >> MdpMinorShift;
+ devnum = minor(stb2.st_rdev) >> MdpMinorShift;
else
- devnum = minor(stb.st_rdev);
+ devnum = minor(stb2.st_rdev);
if (mddev_busy(use_partitions ? (-1-devnum) : devnum))
devnum = -1;
}
@@ -306,6 +308,7 @@ int Incremental(char *devname, int verbose, int runstop,
/* - create the array */
/* - add the device */
struct mdinfo *sra;
+ struct mdinfo dinfo;
if (set_array_info(mdfd, st, &info) != 0) {
fprintf(stderr, Name ": failed to set array info for %s: %s\n",
@@ -314,9 +317,10 @@ int Incremental(char *devname, int verbose, int runstop,
return 2;
}
- info.disk.major = major(stb.st_rdev);
- info.disk.minor = minor(stb.st_rdev);
- if (add_disk(mdfd, st, &info, &info) != 0) {
+ dinfo = info;
+ dinfo.disk.major = major(stb.st_rdev);
+ dinfo.disk.minor = minor(stb.st_rdev);
+ if (add_disk(mdfd, st, &info, &dinfo) != 0) {
fprintf(stderr, Name ": failed to add %s to %s: %s.\n",
devname, chosen_name, strerror(errno));
ioctl(mdfd, STOP_ARRAY, 0);
@@ -337,6 +341,7 @@ int Incremental(char *devname, int verbose, int runstop,
sysfs_free(sra);
return 2;
}
+ info.array.working_disks = 1;
sysfs_free(sra);
} else {
/* 5b/ if it does */
@@ -348,7 +353,7 @@ int Incremental(char *devname, int verbose, int runstop,
int err;
struct mdinfo *sra;
struct supertype *st2;
- struct mdinfo info2;
+ struct mdinfo info2, *d;
sra = sysfs_read(mdfd, devnum, (GET_DEVS | GET_STATE));
sprintf(dn, "%d:%d", sra->devs->disk.major,
@@ -380,6 +385,9 @@ int Incremental(char *devname, int verbose, int runstop,
}
info2.disk.major = major(stb.st_rdev);
info2.disk.minor = minor(stb.st_rdev);
+ /* add disk needs to know about containers */
+ if (st->ss->external)
+ sra->array.level = LEVEL_CONTAINER;
err = add_disk(mdfd, st2, sra, &info2);
if (err < 0 && errno == EBUSY) {
/* could be another device present with the same
@@ -395,6 +403,10 @@ int Incremental(char *devname, int verbose, int runstop,
close(mdfd);
return 2;
}
+ info.array.working_disks = 0;
+ for (d = sra->devs; d; d=d->next)
+ info.array.working_disks ++;
+
}
/* 6/ Make sure /var/run/mdadm.map contains this array. */
map_update(&map, devnum,
@@ -405,6 +417,11 @@ int Incremental(char *devname, int verbose, int runstop,
/* 7a/ if not, finish with success. */
if (info.array.level == LEVEL_CONTAINER) {
/* Try to assemble within the container */
+ close(mdfd);
+ if (verbose >= 0)
+ fprintf(stderr, Name
+ ": container %s now has %d devices\n",
+ chosen_name, info.array.working_disks);
return Incremental(chosen_name, verbose, runstop,
NULL, homehost, autof);
}
@@ -762,52 +779,59 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
char chosen_name[1024];
int usepart = 1;
char *n;
- int working = 0;
+ int working = 0, preexist = 0;
+ struct map_ent *mp, *map = NULL;
if ((autof&7) == 3 || (autof&7) == 5)
usepart = 0;
- n = ra->name;
- if (*n == 'd')
- n++;
- if (*n) {
- devnum = strtoul(n, &n, 10);
- if (devnum >= 0 && (*n == 0 || *n == ' ')) {
- /* Use this devnum */
- usepart = (ra->name[0] == 'd');
- if (mddev_busy(usepart ? (-1-devnum) : devnum))
- devnum = -1;
- } else
- devnum = -1;
- }
+ mp = map_by_uuid(&map, ra->uuid);
+ if (mp)
+ devnum = mp->devnum;
+ else {
- if (devnum < 0) {
- char *nm = ra->name;
- char nbuf[1024];
- struct stat stb;
- if (strchr(nm, ':'))
- nm = strchr(nm, ':')+1;
- sprintf(nbuf, "/dev/md/%s", nm);
-
- if (stat(nbuf, &stb) == 0 &&
- S_ISBLK(stb.st_mode) &&
- major(stb.st_rdev) == (usepart ?
- get_mdp_major() : MD_MAJOR)){
- if (usepart)
- devnum = minor(stb.st_rdev)
- >> MdpMinorShift;
- else
- devnum = minor(stb.st_rdev);
- if (mddev_busy(usepart ? (-1-devnum) : devnum))
+ n = ra->name;
+ if (*n == 'd')
+ n++;
+ if (*n && devnum < 0) {
+ devnum = strtoul(n, &n, 10);
+ if (devnum >= 0 && (*n == 0 || *n == ' ')) {
+ /* Use this devnum */
+ usepart = (ra->name[0] == 'd');
+ if (mddev_busy(usepart ? (-1-devnum) : devnum))
+ devnum = -1;
+ } else
devnum = -1;
}
- }
- if (devnum >= 0)
- devnum = usepart ? (-1-devnum) : devnum;
- else
- devnum = find_free_devnum(usepart);
- mdfd = open_mddev_devnum(NULL, devnum, ra->name,
+ if (devnum < 0) {
+ char *nm = ra->name;
+ char nbuf[1024];
+ struct stat stb;
+ if (strchr(nm, ':'))
+ nm = strchr(nm, ':')+1;
+ sprintf(nbuf, "/dev/md/%s", nm);
+
+ if (stat(nbuf, &stb) == 0 &&
+ S_ISBLK(stb.st_mode) &&
+ major(stb.st_rdev) == (usepart ?
+ get_mdp_major() : MD_MAJOR)){
+ if (usepart)
+ devnum = minor(stb.st_rdev)
+ >> MdpMinorShift;
+ else
+ devnum = minor(stb.st_rdev);
+ if (mddev_busy(usepart ? (-1-devnum) : devnum))
+ devnum = -1;
+ }
+ }
+
+ if (devnum >= 0)
+ devnum = usepart ? (-1-devnum) : devnum;
+ else
+ devnum = find_free_devnum(usepart);
+ }
+ mdfd = open_mddev_devnum(mp ? mp->path : NULL, devnum, ra->name,
chosen_name, autof>>3);
if (mdfd < 0) {
@@ -821,8 +845,12 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
for (dev = ra->devs; dev; dev = dev->next)
if (sysfs_add_disk(ra, dev) == 0)
working++;
-
- if (runstop > 0 || working >= ra->array.working_disks) {
+ else if (errno == EEXIST)
+ preexist++;
+ if (working == 0)
+ /* Nothing new, don't try to start */ ;
+ else if (runstop > 0 ||
+ (working + preexist) >= ra->array.working_disks) {
switch(ra->array.level) {
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
@@ -840,16 +868,25 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
break;
}
sysfs_set_safemode(ra, ra->safe_mode_delay);
- if (verbose >= 0)
- printf("Started %s with %d devices\n",
- chosen_name, working);
+ if (verbose >= 0) {
+ fprintf(stderr, Name
+ "Started %s with %d devices",
+ chosen_name, working + preexist);
+ if (preexist)
+ fprintf(stderr, " (%d new)", working);
+ fprintf(stderr, "\n");
+ }
/* FIXME should have an O_EXCL and wait for read-auto */
} else
if (verbose >= 0)
- printf("%s assembled with %d devices but "
- "not started\n",
- chosen_name, working);
+ fprintf(stderr, Name
+ "%s assembled with %d devices but "
+ "not started\n",
+ chosen_name, working);
close(mdfd);
+ map_update(&map, devnum,
+ ra->text_version,
+ ra->uuid, chosen_name);
}
return 0;
}
diff --git a/mapfile.c b/mapfile.c
index cf2ca2bf..955a1f98 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -117,10 +117,12 @@ void map_read(struct map_ent **melp)
return;
while (fgets(buf, sizeof(buf), f)) {
- if (sscanf(buf, " md%1[p]%d %s %x:%x:%x:%x %200s",
+ if (sscanf(buf, " %3[mdp]%d %s %x:%x:%x:%x %200s",
nam, &devnum, metadata, uuid, uuid+1,
- uuid+2, uuid+3, path) == 9) {
- if (nam[0] == 'p')
+ uuid+2, uuid+3, path) == 8) {
+ if (strncmp(nam, "md", 2) != 0)
+ continue;
+ if (nam[2] == 'p')
devnum = -1 - devnum;
map_add(melp, devnum, metadata, uuid, path);
}
diff --git a/mdopen.c b/mdopen.c
index 4fbcb484..0b9498cc 100644
--- a/mdopen.c
+++ b/mdopen.c
@@ -282,7 +282,7 @@ int open_mddev_devnum(char *devname, int devnum, char *name,
if (devname)
strcpy(chosen_name, devname);
- else if (name && strchr(name,'/') == NULL) {
+ else if (name && name[0] && strchr(name,'/') == NULL) {
char *n = strchr(name, ':');
if (n) n++; else n = name;
if (isdigit(*n) && devnum < 0)
diff --git a/super-ddf.c b/super-ddf.c
index 957a1341..2c82fd9a 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1194,19 +1194,21 @@ static void uuid_from_super_ddf(struct supertype *st, int uuid[4])
*/
struct ddf_super *ddf = st->sb;
struct vcl *vcl = ddf->currentconf;
+ char *guid;
+ char buf[20];
+ struct sha1_ctx ctx;
- if (!vcl)
- memset(uuid, 0, sizeof (uuid));
- else {
- char buf[20];
- struct sha1_ctx ctx;
- sha1_init_ctx(&ctx);
- sha1_process_bytes(&vcl->conf.guid, DDF_GUID_LEN, &ctx);
- if (vcl->conf.sec_elmnt_count > 1)
- sha1_process_bytes(&vcl->conf.sec_elmnt_seq, 1, &ctx);
- sha1_finish_ctx(&ctx, buf);
- memcpy(uuid, buf, sizeof(uuid));
- }
+ if (vcl)
+ guid = vcl->conf.guid;
+ else
+ guid = ddf->anchor.guid;
+
+ sha1_init_ctx(&ctx);
+ sha1_process_bytes(guid, DDF_GUID_LEN, &ctx);
+ if (vcl && vcl->conf.sec_elmnt_count > 1)
+ sha1_process_bytes(&vcl->conf.sec_elmnt_seq, 1, &ctx);
+ sha1_finish_ctx(&ctx, buf);
+ memcpy(uuid, buf, 4*4);
}
static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info);
@@ -1248,15 +1250,15 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
info->reshape_active = 0;
+ info->name[0] = 0;
info->array.major_version = -1;
info->array.minor_version = -2;
strcpy(info->text_version, "ddf");
info->safe_mode_delay = 0;
-// uuid_from_super_ddf(info->uuid, sbv);
+ uuid_from_super_ddf(st, info->uuid);
-// info->name[] ?? ;
}
static int rlq_to_layout(int rlq, int prl, int raiddisks);
@@ -1313,7 +1315,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
st->subarray);
info->safe_mode_delay = 200;
-// info->name[] ?? ;
+ info->name[0] = 0;
}
@@ -2623,6 +2625,10 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
this->array.size = this->component_size / 2;
this->container_member = i;
+ ddf->currentconf = vc;
+ uuid_from_super_ddf(st, this->uuid);
+ ddf->currentconf = NULL;
+
sprintf(this->text_version, "/%s/%d",
devnum2devname(st->container_dev),
this->container_member);
diff --git a/super-intel.c b/super-intel.c
index cc321825..ff86e094 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -708,6 +708,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
info->safe_mode_delay = 0;
info->disk.number = -1;
info->disk.state = 0;
+ info->name[0] = 0;
if (super->disks) {
disk = &super->disks->disk;