summaryrefslogtreecommitdiff
path: root/Assemble.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-10-18 15:31:20 +1100
committerNeilBrown <neilb@suse.de>2012-10-18 15:31:20 +1100
commit95425a89fc31ea0e98f536ef0b8616a0ec317af2 (patch)
treef7a34a0f847cf63c2fd1c200c06281a966d085b6 /Assemble.c
parenta994592d75e64b50201121f6357ea73a0b7d4e6e (diff)
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>
Diffstat (limited to 'Assemble.c')
-rw-r--r--Assemble.c324
1 files changed, 173 insertions, 151 deletions
diff --git a/Assemble.c b/Assemble.c
index a1e27918..2f1d2de6 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -129,145 +129,20 @@ static int ident_matches(struct mddev_ident *ident,
return 1;
}
-int Assemble(struct supertype *st, char *mddev,
- struct mddev_ident *ident,
- struct mddev_dev *devlist,
- struct context *c)
+static int select_devices(struct mddev_dev *devlist,
+ struct mddev_ident *ident,
+ struct supertype **stp,
+ 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 mdinfo info;
+ int num_devs;
+ struct supertype *st = *stp;
struct mdinfo *content = NULL;
- struct mdinfo *pre_exist = NULL;
- char *avail;
- int nextspare = 0;
- char *name = NULL;
- char chosen_name[1024];
+ int report_missmatch = ((inargv && c->verbose >= 0) || c->verbose > 0);
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;
while (tmpdev) {
@@ -279,12 +154,6 @@ int Assemble(struct supertype *st, char *mddev,
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
* that match the criterea, if that is possible.
* We flag the ones we like with 'used'.
@@ -299,7 +168,8 @@ int Assemble(struct supertype *st, char *mddev,
struct dev_policy *pol = NULL;
int found_container = 0;
- if (tmpdev->used > 1) continue;
+ if (tmpdev->used > 1)
+ continue;
if (ident->devices &&
!match_oneof(ident->devices, devname)) {
@@ -400,7 +270,7 @@ int Assemble(struct supertype *st, char *mddev,
st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
- return 1;
+ return -1;
}
if (found_container) {
@@ -431,7 +301,7 @@ int Assemble(struct supertype *st, char *mddev,
/* we have a uuid */
int uuid[4];
- content = &info;
+ content = *contentp;
tst->ss->getinfo_super(tst, content, NULL);
if (!parse_uuid(ident->container, uuid) ||
@@ -483,7 +353,7 @@ int Assemble(struct supertype *st, char *mddev,
st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
- return 1;
+ return -1;
}
if (c->verbose > 0)
pr_err("found match on member %s in %s\n",
@@ -494,7 +364,7 @@ int Assemble(struct supertype *st, char *mddev,
goto loop;
} else {
- content = &info;
+ content = *contentp;
tst->ss->getinfo_super(tst, content, NULL);
if (!ident_matches(ident, content, tst,
@@ -570,7 +440,7 @@ int Assemble(struct supertype *st, char *mddev,
st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
- return 1;
+ return -1;
}
tmpdev->used = 1;
}
@@ -596,7 +466,7 @@ int Assemble(struct supertype *st, char *mddev,
if (tmpdev->used != 3)
continue;
tmpdev->used = 1;
- content = &info;
+ content = *contentp;
if (!st->sb) {
/* we need sb from one of the spares */
@@ -636,13 +506,165 @@ int Assemble(struct supertype *st, char *mddev,
}
}
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)
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
* array device.
* However there is a risk that we are racing with "mdadm -I"