Assemble: allow members of containers to be assembled and auto-assembled.
Try to treat members of containers much like other arrays for assembly. We still look through the list of devices for a match (it will be the container), then find the relevant 'info' and try to assemble the array. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
52437b4f08
commit
9008ed1c96
91
Assemble.c
91
Assemble.c
|
@ -50,7 +50,7 @@ static int name_matches(char *found, char *required, char *homehost)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*static */ int is_member_busy(char *metadata_version)
|
||||
static int is_member_busy(char *metadata_version)
|
||||
{
|
||||
/* check if the given member array is active */
|
||||
struct mdstat_ent *mdstat = mdstat_read(1, 0);
|
||||
|
@ -273,6 +273,62 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
}
|
||||
if (dfd >= 0) close(dfd);
|
||||
|
||||
if (tst && tst->sb && tst->ss->container_content
|
||||
&& tst->loaded_container) {
|
||||
/* tmpdev is a container. We need to be either
|
||||
* looking for a member, or auto-assembling
|
||||
*/
|
||||
if (st) {
|
||||
/* already found some components, this cannot
|
||||
* be another one.
|
||||
*/
|
||||
if (report_missmatch)
|
||||
fprintf(stderr, Name ": %s is a container, but we are looking for components\n",
|
||||
devname);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (ident->container) {
|
||||
if (ident->container[0] == '/' &&
|
||||
!same_dev(ident->container, devname)) {
|
||||
if (report_missmatch)
|
||||
fprintf(stderr, Name ": %s is not the container required (%s)\n",
|
||||
devname, ident->container);
|
||||
goto loop;
|
||||
}
|
||||
if (ident->container[0] != '/') {
|
||||
/* we have a uuid */
|
||||
int uuid[4];
|
||||
if (!parse_uuid(ident->container, uuid) ||
|
||||
!same_uuid(content->uuid, uuid, tst->ss->swapuuid)) {
|
||||
if (report_missmatch)
|
||||
fprintf(stderr, Name ": %s has wrong UUID to be required container\n",
|
||||
devname);
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* It is worth looking inside this container.
|
||||
*/
|
||||
next_member:
|
||||
if (tmpdev->content)
|
||||
content = tmpdev->content;
|
||||
else
|
||||
content = tst->ss->container_content(tst);
|
||||
|
||||
tmpdev->content = content->next;
|
||||
if (tmpdev->content == NULL)
|
||||
tmpdev->used = 1;
|
||||
|
||||
} else if (ident->container || ident->member) {
|
||||
/* No chance of this matching if we don't have
|
||||
* a container */
|
||||
if (report_missmatch)
|
||||
fprintf(stderr, Name "%s is not a container, and one is required.\n",
|
||||
devname);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
|
||||
(!tst || !tst->sb ||
|
||||
same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0)) {
|
||||
|
@ -332,6 +388,30 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (tst && tst->sb && tst->ss->container_content
|
||||
&& tst->loaded_container) {
|
||||
/* we have the one container we need, don't keep
|
||||
* looking. If the chosen member is active, skip.
|
||||
*/
|
||||
if (is_member_busy(content->text_version)) {
|
||||
if (auto_assem)
|
||||
goto loop;
|
||||
fprintf(stderr, Name ": member %s in %s is already assembled\n",
|
||||
content->text_version,
|
||||
devname);
|
||||
tst->ss->free_super(tst);
|
||||
return 1;
|
||||
}
|
||||
st = tst; tst = NULL;
|
||||
if (!auto_assem && tmpdev->next != NULL) {
|
||||
fprintf(stderr, Name ": %s is a container, but is not "
|
||||
"only device given: confused and aborting\n",
|
||||
devname);
|
||||
st->ss->free_super(st);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (st == NULL)
|
||||
st = dup_super(tst);
|
||||
if (st->minor_version == -1)
|
||||
|
@ -380,6 +460,8 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
tmpdev->used = 1;
|
||||
|
||||
loop:
|
||||
if (tmpdev->content)
|
||||
goto next_member;
|
||||
if (tst)
|
||||
tst->ss->free_super(tst);
|
||||
}
|
||||
|
@ -458,6 +540,13 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
}
|
||||
ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
|
||||
|
||||
#ifndef MDASSEMBLE
|
||||
if (content != &info) {
|
||||
/* This is a member of a container. Try starting the array. */
|
||||
return assemble_container_content(st, mdfd, content, runstop,
|
||||
chosen_name, verbose);
|
||||
}
|
||||
#endif
|
||||
/* Ok, no bad inconsistancy, we can try updating etc */
|
||||
bitmap_done = 0;
|
||||
for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
|
||||
|
|
3
config.c
3
config.c
|
@ -261,6 +261,7 @@ mddev_dev_t load_partitions(void)
|
|||
d->devname = strdup(name);
|
||||
d->next = rv;
|
||||
d->used = 0;
|
||||
d->content = NULL;
|
||||
rv = d;
|
||||
}
|
||||
fclose(f);
|
||||
|
@ -290,6 +291,7 @@ mddev_dev_t load_containers(void)
|
|||
}
|
||||
d->next = rv;
|
||||
d->used = 0;
|
||||
d->content = NULL;
|
||||
rv = d;
|
||||
}
|
||||
free_mdstat(mdstat);
|
||||
|
@ -803,6 +805,7 @@ mddev_dev_t conf_get_devs()
|
|||
t->devname = strdup(globbuf.gl_pathv[i]);
|
||||
t->next = dlist;
|
||||
t->used = 0;
|
||||
t->content = NULL;
|
||||
dlist = t;
|
||||
/* printf("one dev is %s\n", t->devname);*/
|
||||
}
|
||||
|
|
3
mdadm.c
3
mdadm.c
|
@ -256,6 +256,7 @@ int main(int argc, char *argv[])
|
|||
dv->writemostly = writemostly;
|
||||
dv->re_add = re_add;
|
||||
dv->used = 0;
|
||||
dv->content = NULL;
|
||||
dv->next = NULL;
|
||||
*devlistend = dv;
|
||||
devlistend = &dv->next;
|
||||
|
@ -308,6 +309,8 @@ int main(int argc, char *argv[])
|
|||
dv->disposition = devmode;
|
||||
dv->writemostly = writemostly;
|
||||
dv->re_add = re_add;
|
||||
dv->used = 0;
|
||||
dv->content = NULL;
|
||||
dv->next = NULL;
|
||||
*devlistend = dv;
|
||||
devlistend = &dv->next;
|
||||
|
|
3
mdadm.h
3
mdadm.h
|
@ -278,6 +278,8 @@ typedef struct mddev_dev_s {
|
|||
char writemostly; /* 1 for 'set writemostly', 2 for 'clear writemostly' */
|
||||
char re_add;
|
||||
char used; /* set when used */
|
||||
struct mdinfo *content; /* If devname is a container, this might list
|
||||
* the remaining member arrays. */
|
||||
struct mddev_dev_s *next;
|
||||
} *mddev_dev_t;
|
||||
|
||||
|
@ -758,6 +760,7 @@ extern int get_mdp_major(void);
|
|||
extern int dev_open(char *dev, int flags);
|
||||
extern int open_dev_excl(int devnum);
|
||||
extern int is_standard(char *dev, int *nump);
|
||||
extern int same_dev(char *one, char *two);
|
||||
|
||||
extern int parse_auto(char *str, char *msg, int config);
|
||||
extern mddev_ident_t conf_get_ident(char *dev);
|
||||
|
|
14
util.c
14
util.c
|
@ -828,6 +828,20 @@ int open_dev_excl(int devnum)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int same_dev(char *one, char *two)
|
||||
{
|
||||
struct stat st1, st2;
|
||||
if (stat(one, &st1) != 0)
|
||||
return 0;
|
||||
if (stat(two, &st2) != 0)
|
||||
return 0;
|
||||
if ((st1.st_mode & S_IFMT) != S_IFBLK)
|
||||
return 0;
|
||||
if ((st2.st_mode & S_IFMT) != S_IFBLK)
|
||||
return 0;
|
||||
return st1.st_rdev == st2.st_rdev;
|
||||
}
|
||||
|
||||
struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL };
|
||||
|
||||
#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
|
||||
|
|
Loading…
Reference in New Issue