Assemble: split out select_devices function.
Assemble() is way too big. This patch starts cleaning it up by pulling the 'select_devices()' function. This examines the device to make sure they all belong to one array, or select those that do (depending on exact use case). Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
a994592d75
commit
95425a89fc
324
Assemble.c
324
Assemble.c
|
@ -129,145 +129,20 @@ static int ident_matches(struct mddev_ident *ident,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Assemble(struct supertype *st, char *mddev,
|
static int select_devices(struct mddev_dev *devlist,
|
||||||
struct mddev_ident *ident,
|
struct mddev_ident *ident,
|
||||||
struct mddev_dev *devlist,
|
struct supertype **stp,
|
||||||
struct context *c)
|
struct mdinfo **contentp,
|
||||||
|
struct context *c,
|
||||||
|
int inargv, int auto_assem)
|
||||||
|
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* The task of Assemble is to find a collection of
|
|
||||||
* devices that should (according to their superblocks)
|
|
||||||
* form an array, and to give this collection to the MD driver.
|
|
||||||
* In Linux-2.4 and later, this involves submitting a
|
|
||||||
* SET_ARRAY_INFO ioctl with no arg - to prepare
|
|
||||||
* the array - and then submit a number of
|
|
||||||
* ADD_NEW_DISK ioctls to add disks into
|
|
||||||
* the array. Finally RUN_ARRAY might
|
|
||||||
* be submitted to start the array.
|
|
||||||
*
|
|
||||||
* 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 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)
|
|
||||||
*
|
|
||||||
* If mddev is set, we try to determine state of md.
|
|
||||||
* check version - must be at least 0.90.0
|
|
||||||
* check kernel version. must be at least 2.4.
|
|
||||||
* If not, we can possibly fall back on START_ARRAY
|
|
||||||
* Try to GET_ARRAY_INFO.
|
|
||||||
* If possible, give up
|
|
||||||
* If not, try to STOP_ARRAY just to make sure
|
|
||||||
*
|
|
||||||
* If !uuidset and scan, look in conf-file for uuid
|
|
||||||
* If not found, give up
|
|
||||||
* If !devlist and scan and uuidset, get list of devs from conf-file
|
|
||||||
*
|
|
||||||
* 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 superblock - discard if different
|
|
||||||
* Record events, devicenum
|
|
||||||
* This should give us a list of devices for the array
|
|
||||||
* We should collect the most recent event number
|
|
||||||
*
|
|
||||||
* Count disks with recent enough event count
|
|
||||||
* While force && !enough disks
|
|
||||||
* Choose newest rejected disks, update event count
|
|
||||||
* mark clean and rewrite superblock
|
|
||||||
* If recent kernel:
|
|
||||||
* SET_ARRAY_INFO
|
|
||||||
* foreach device with recent events : ADD_NEW_DISK
|
|
||||||
* if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
|
|
||||||
* If old kernel:
|
|
||||||
* Check the device numbers in superblock are right
|
|
||||||
* update superblock if any changes
|
|
||||||
* START_ARRAY
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int mdfd;
|
|
||||||
int clean;
|
|
||||||
int auto_assem = (mddev == NULL && !ident->uuid_set &&
|
|
||||||
ident->super_minor == UnSet && ident->name[0] == 0
|
|
||||||
&& (ident->container == NULL || ident->member == NULL));
|
|
||||||
int old_linux = 0;
|
|
||||||
int vers = vers; /* Keep gcc quite - it really is initialised */
|
|
||||||
struct {
|
|
||||||
char *devname;
|
|
||||||
int uptodate; /* set once we decide that this device is as
|
|
||||||
* recent as everything else in the array.
|
|
||||||
*/
|
|
||||||
int included; /* set if the device is already in the array
|
|
||||||
* due to a previous '-I'
|
|
||||||
*/
|
|
||||||
struct mdinfo i;
|
|
||||||
} *devices;
|
|
||||||
char *devmap;
|
|
||||||
int *best = NULL; /* indexed by raid_disk */
|
|
||||||
int bestcnt = 0;
|
|
||||||
int devcnt = 0;
|
|
||||||
unsigned int okcnt, sparecnt, rebuilding_cnt;
|
|
||||||
unsigned int req_cnt;
|
|
||||||
int i;
|
|
||||||
int most_recent = 0;
|
|
||||||
int chosen_drive;
|
|
||||||
int change = 0;
|
|
||||||
int inargv = 0;
|
|
||||||
int report_missmatch;
|
|
||||||
#ifndef MDASSEMBLE
|
|
||||||
int bitmap_done;
|
|
||||||
#endif
|
|
||||||
int start_partial_ok = (c->runstop >= 0) &&
|
|
||||||
(c->force || devlist==NULL || auto_assem);
|
|
||||||
unsigned int num_devs;
|
|
||||||
struct mddev_dev *tmpdev;
|
struct mddev_dev *tmpdev;
|
||||||
struct mdinfo info;
|
int num_devs;
|
||||||
|
struct supertype *st = *stp;
|
||||||
struct mdinfo *content = NULL;
|
struct mdinfo *content = NULL;
|
||||||
struct mdinfo *pre_exist = NULL;
|
int report_missmatch = ((inargv && c->verbose >= 0) || c->verbose > 0);
|
||||||
char *avail;
|
|
||||||
int nextspare = 0;
|
|
||||||
char *name = NULL;
|
|
||||||
char chosen_name[1024];
|
|
||||||
struct domainlist *domains = NULL;
|
struct domainlist *domains = NULL;
|
||||||
struct map_ent *map = NULL;
|
|
||||||
struct map_ent *mp;
|
|
||||||
|
|
||||||
if (get_linux_version() < 2004000)
|
|
||||||
old_linux = 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If any subdevs are listed, then any that don't
|
|
||||||
* match ident are discarded. Remainder must all match and
|
|
||||||
* become the array.
|
|
||||||
* If no subdevs, then we scan all devices in the config file, but
|
|
||||||
* there must be something in the identity
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!devlist &&
|
|
||||||
ident->uuid_set == 0 &&
|
|
||||||
(ident->super_minor < 0 || ident->super_minor == UnSet) &&
|
|
||||||
ident->name[0] == 0 &&
|
|
||||||
(ident->container == NULL || ident->member == NULL) &&
|
|
||||||
ident->devices == NULL) {
|
|
||||||
pr_err("No identity information available for %s - cannot assemble.\n",
|
|
||||||
mddev ? mddev : "further assembly");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devlist == NULL)
|
|
||||||
devlist = conf_get_devs();
|
|
||||||
else if (mddev)
|
|
||||||
inargv = 1;
|
|
||||||
|
|
||||||
report_missmatch = ((inargv && c->verbose >= 0) || c->verbose > 0);
|
|
||||||
try_again:
|
|
||||||
/* We come back here when doing auto-assembly and attempting some
|
|
||||||
* set of devices failed. Those are now marked as ->used==2 and
|
|
||||||
* we ignore them and try again
|
|
||||||
*/
|
|
||||||
|
|
||||||
tmpdev = devlist; num_devs = 0;
|
tmpdev = devlist; num_devs = 0;
|
||||||
while (tmpdev) {
|
while (tmpdev) {
|
||||||
|
@ -279,12 +154,6 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
tmpdev = tmpdev->next;
|
tmpdev = tmpdev->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!st && ident->st) st = ident->st;
|
|
||||||
|
|
||||||
if (c->verbose>0)
|
|
||||||
pr_err("looking for devices for %s\n",
|
|
||||||
mddev ? mddev : "further assembly");
|
|
||||||
|
|
||||||
/* first walk the list of devices to find a consistent set
|
/* first walk the list of devices to find a consistent set
|
||||||
* that match the criterea, if that is possible.
|
* that match the criterea, if that is possible.
|
||||||
* We flag the ones we like with 'used'.
|
* We flag the ones we like with 'used'.
|
||||||
|
@ -299,7 +168,8 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
struct dev_policy *pol = NULL;
|
struct dev_policy *pol = NULL;
|
||||||
int found_container = 0;
|
int found_container = 0;
|
||||||
|
|
||||||
if (tmpdev->used > 1) continue;
|
if (tmpdev->used > 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (ident->devices &&
|
if (ident->devices &&
|
||||||
!match_oneof(ident->devices, devname)) {
|
!match_oneof(ident->devices, devname)) {
|
||||||
|
@ -400,7 +270,7 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
st->ss->free_super(st);
|
st->ss->free_super(st);
|
||||||
dev_policy_free(pol);
|
dev_policy_free(pol);
|
||||||
domain_free(domains);
|
domain_free(domains);
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found_container) {
|
if (found_container) {
|
||||||
|
@ -431,7 +301,7 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
/* we have a uuid */
|
/* we have a uuid */
|
||||||
int uuid[4];
|
int uuid[4];
|
||||||
|
|
||||||
content = &info;
|
content = *contentp;
|
||||||
tst->ss->getinfo_super(tst, content, NULL);
|
tst->ss->getinfo_super(tst, content, NULL);
|
||||||
|
|
||||||
if (!parse_uuid(ident->container, uuid) ||
|
if (!parse_uuid(ident->container, uuid) ||
|
||||||
|
@ -483,7 +353,7 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
st->ss->free_super(st);
|
st->ss->free_super(st);
|
||||||
dev_policy_free(pol);
|
dev_policy_free(pol);
|
||||||
domain_free(domains);
|
domain_free(domains);
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (c->verbose > 0)
|
if (c->verbose > 0)
|
||||||
pr_err("found match on member %s in %s\n",
|
pr_err("found match on member %s in %s\n",
|
||||||
|
@ -494,7 +364,7 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
goto loop;
|
goto loop;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
content = &info;
|
content = *contentp;
|
||||||
tst->ss->getinfo_super(tst, content, NULL);
|
tst->ss->getinfo_super(tst, content, NULL);
|
||||||
|
|
||||||
if (!ident_matches(ident, content, tst,
|
if (!ident_matches(ident, content, tst,
|
||||||
|
@ -570,7 +440,7 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
st->ss->free_super(st);
|
st->ss->free_super(st);
|
||||||
dev_policy_free(pol);
|
dev_policy_free(pol);
|
||||||
domain_free(domains);
|
domain_free(domains);
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
tmpdev->used = 1;
|
tmpdev->used = 1;
|
||||||
}
|
}
|
||||||
|
@ -596,7 +466,7 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
if (tmpdev->used != 3)
|
if (tmpdev->used != 3)
|
||||||
continue;
|
continue;
|
||||||
tmpdev->used = 1;
|
tmpdev->used = 1;
|
||||||
content = &info;
|
content = *contentp;
|
||||||
|
|
||||||
if (!st->sb) {
|
if (!st->sb) {
|
||||||
/* we need sb from one of the spares */
|
/* we need sb from one of the spares */
|
||||||
|
@ -636,13 +506,165 @@ int Assemble(struct supertype *st, char *mddev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
domain_free(domains);
|
domain_free(domains);
|
||||||
|
*stp = st;
|
||||||
|
if (st && st->sb && content == *contentp)
|
||||||
|
st->ss->getinfo_super(st, content, NULL);
|
||||||
|
*contentp = content;
|
||||||
|
|
||||||
|
return num_devs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Assemble(struct supertype *st, char *mddev,
|
||||||
|
struct mddev_ident *ident,
|
||||||
|
struct mddev_dev *devlist,
|
||||||
|
struct context *c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The task of Assemble is to find a collection of
|
||||||
|
* devices that should (according to their superblocks)
|
||||||
|
* form an array, and to give this collection to the MD driver.
|
||||||
|
* In Linux-2.4 and later, this involves submitting a
|
||||||
|
* SET_ARRAY_INFO ioctl with no arg - to prepare
|
||||||
|
* the array - and then submit a number of
|
||||||
|
* ADD_NEW_DISK ioctls to add disks into
|
||||||
|
* the array. Finally RUN_ARRAY might
|
||||||
|
* be submitted to start the array.
|
||||||
|
*
|
||||||
|
* 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 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)
|
||||||
|
*
|
||||||
|
* If mddev is set, we try to determine state of md.
|
||||||
|
* check version - must be at least 0.90.0
|
||||||
|
* check kernel version. must be at least 2.4.
|
||||||
|
* If not, we can possibly fall back on START_ARRAY
|
||||||
|
* Try to GET_ARRAY_INFO.
|
||||||
|
* If possible, give up
|
||||||
|
* If not, try to STOP_ARRAY just to make sure
|
||||||
|
*
|
||||||
|
* If !uuidset and scan, look in conf-file for uuid
|
||||||
|
* If not found, give up
|
||||||
|
* If !devlist and scan and uuidset, get list of devs from conf-file
|
||||||
|
*
|
||||||
|
* 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 superblock - discard if different
|
||||||
|
* Record events, devicenum
|
||||||
|
* This should give us a list of devices for the array
|
||||||
|
* We should collect the most recent event number
|
||||||
|
*
|
||||||
|
* Count disks with recent enough event count
|
||||||
|
* While force && !enough disks
|
||||||
|
* Choose newest rejected disks, update event count
|
||||||
|
* mark clean and rewrite superblock
|
||||||
|
* If recent kernel:
|
||||||
|
* SET_ARRAY_INFO
|
||||||
|
* foreach device with recent events : ADD_NEW_DISK
|
||||||
|
* if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
|
||||||
|
* If old kernel:
|
||||||
|
* Check the device numbers in superblock are right
|
||||||
|
* update superblock if any changes
|
||||||
|
* START_ARRAY
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int mdfd;
|
||||||
|
int clean;
|
||||||
|
int auto_assem = (mddev == NULL && !ident->uuid_set &&
|
||||||
|
ident->super_minor == UnSet && ident->name[0] == 0
|
||||||
|
&& (ident->container == NULL || ident->member == NULL));
|
||||||
|
int old_linux = 0;
|
||||||
|
int vers = vers; /* Keep gcc quite - it really is initialised */
|
||||||
|
struct {
|
||||||
|
char *devname;
|
||||||
|
int uptodate; /* set once we decide that this device is as
|
||||||
|
* recent as everything else in the array.
|
||||||
|
*/
|
||||||
|
int included; /* set if the device is already in the array
|
||||||
|
* due to a previous '-I'
|
||||||
|
*/
|
||||||
|
struct mdinfo i;
|
||||||
|
} *devices;
|
||||||
|
char *devmap;
|
||||||
|
int *best = NULL; /* indexed by raid_disk */
|
||||||
|
int bestcnt = 0;
|
||||||
|
int devcnt = 0;
|
||||||
|
unsigned int okcnt, sparecnt, rebuilding_cnt;
|
||||||
|
unsigned int req_cnt;
|
||||||
|
int i;
|
||||||
|
int most_recent = 0;
|
||||||
|
int chosen_drive;
|
||||||
|
int change = 0;
|
||||||
|
int inargv = 0;
|
||||||
|
#ifndef MDASSEMBLE
|
||||||
|
int bitmap_done;
|
||||||
|
#endif
|
||||||
|
int start_partial_ok = (c->runstop >= 0) &&
|
||||||
|
(c->force || devlist==NULL || auto_assem);
|
||||||
|
int num_devs;
|
||||||
|
struct mddev_dev *tmpdev;
|
||||||
|
struct mdinfo info;
|
||||||
|
struct mdinfo *content = NULL;
|
||||||
|
struct mdinfo *pre_exist = NULL;
|
||||||
|
char *avail;
|
||||||
|
int nextspare = 0;
|
||||||
|
char *name = NULL;
|
||||||
|
char chosen_name[1024];
|
||||||
|
struct map_ent *map = NULL;
|
||||||
|
struct map_ent *mp;
|
||||||
|
|
||||||
|
if (get_linux_version() < 2004000)
|
||||||
|
old_linux = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any subdevs are listed, then any that don't
|
||||||
|
* match ident are discarded. Remainder must all match and
|
||||||
|
* become the array.
|
||||||
|
* If no subdevs, then we scan all devices in the config file, but
|
||||||
|
* there must be something in the identity
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!devlist &&
|
||||||
|
ident->uuid_set == 0 &&
|
||||||
|
(ident->super_minor < 0 || ident->super_minor == UnSet) &&
|
||||||
|
ident->name[0] == 0 &&
|
||||||
|
(ident->container == NULL || ident->member == NULL) &&
|
||||||
|
ident->devices == NULL) {
|
||||||
|
pr_err("No identity information available for %s - cannot assemble.\n",
|
||||||
|
mddev ? mddev : "further assembly");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devlist == NULL)
|
||||||
|
devlist = conf_get_devs();
|
||||||
|
else if (mddev)
|
||||||
|
inargv = 1;
|
||||||
|
|
||||||
|
try_again:
|
||||||
|
/* We come back here when doing auto-assembly and attempting some
|
||||||
|
* set of devices failed. Those are now marked as ->used==2 and
|
||||||
|
* we ignore them and try again
|
||||||
|
*/
|
||||||
|
if (!st && ident->st)
|
||||||
|
st = ident->st;
|
||||||
|
if (c->verbose>0)
|
||||||
|
pr_err("looking for devices for %s\n",
|
||||||
|
mddev ? mddev : "further assembly");
|
||||||
|
|
||||||
|
content = &info;
|
||||||
|
num_devs = select_devices(devlist, ident, &st, &content, c,
|
||||||
|
inargv, auto_assem);
|
||||||
|
if (num_devs < 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (!st || !st->sb || !content)
|
if (!st || !st->sb || !content)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (content == &info)
|
|
||||||
st->ss->getinfo_super(st, content, NULL);
|
|
||||||
|
|
||||||
/* We have a full set of devices - we now need to find the
|
/* We have a full set of devices - we now need to find the
|
||||||
* array device.
|
* array device.
|
||||||
* However there is a risk that we are racing with "mdadm -I"
|
* However there is a risk that we are racing with "mdadm -I"
|
||||||
|
|
Loading…
Reference in New Issue