]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Assemble: split out select_devices function.
authorNeilBrown <neilb@suse.de>
Thu, 18 Oct 2012 04:31:20 +0000 (15:31 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 18 Oct 2012 04:31:20 +0000 (15:31 +1100)
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>
Assemble.c

index a1e279181bbf414730dcb4e74dc6264b2f4813a7..2f1d2de6d1d0ef8acb1b21e06fbc6d7bd97a0131 100644 (file)
@@ -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"