]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Use one function chosing spares from container
authorAnna Czarnowska <anna.czarnowska@intel.com>
Wed, 5 Jan 2011 03:34:14 +0000 (14:34 +1100)
committerNeilBrown <neilb@suse.de>
Wed, 5 Jan 2011 03:34:14 +0000 (14:34 +1100)
container_chose_spares in Monitor.c and
get_spares_for_grow in super-intel.c
do the same thing: search for spares in a container.

Another version will also be needed for Incremental
so a more general solution is presented here and
applied in two previous contexts.

Normally domlist==NULL would lead an empty list but
this is typically checked earlier so here it is interpreted
as "do not test domains".

Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Monitor.c
mdadm.h
super-intel.c
util.c

index e79f658b6d0795c21c0cc058db5e02e1b49068c1..00db53f26ffc8a64c44ef3f22fbbe6a6826f1015 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -828,59 +828,34 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
        /* This is similar to choose_spare, but we cannot trust devstate,
         * so we need to read the metadata instead
         */
-
+       struct mdinfo *list;
        struct supertype *st = from->metadata;
        int fd = open(from->devname, O_RDONLY);
        int err;
-       struct mdinfo *disks, *d;
        dev_t dev = 0;
 
        if (fd < 0)
                return 0;
-       if (!st->ss->getinfo_super_disks)
+       if (!st->ss->getinfo_super_disks) {
+               close(fd);
                return 0;
+       }
        
        err = st->ss->load_container(st, fd, NULL);
        close(fd);
        if (err)
                return 0;
-
-       disks = st->ss->getinfo_super_disks(st);
-       st->ss->free_super(st);
-
-       if (!disks)
-               return 0;
        
-       for (d = disks->devs ; d && !dev ; d = d->next) {
-               if (d->disk.state == 0) {
-                       struct dev_policy *pol;
-                       unsigned long long dev_size;
-                       dev = makedev(d->disk.major,d->disk.minor);
-                       
-                       if (min_size &&
-                           dev_size_from_id(dev,  &dev_size) &&
-                           dev_size < min_size) {
-                               dev = 0;
-                               continue;
-                       }
-                       if (from == to)
-                               /* Just checking if destination already has
-                                * a spare, no need to check policy, we are
-                                * done.
-                                */
-                               break;
-
-                       pol = devnum_policy(dev);
-                       if (from->spare_group)
-                               pol_add(&pol, pol_domain,
-                                       from->spare_group, NULL);
-                       if (!domain_test(domlist, pol, to->metadata->ss->name))
-                               dev = 0;
-
-                       dev_policy_free(pol);
-               }
+       /* We only need one spare so full list not needed */
+       list = container_choose_spares(st, min_size, domlist, from->spare_group,
+                                      to->metadata->ss->name, 1);
+       if (list) {
+               struct mdinfo *disks = list->devs;
+               if (disks)
+                       dev = makedev(disks->disk.major, disks->disk.minor);
+               sysfs_free(list);
        }
-       sysfs_free(disks);
+       st->ss->free_super(st);
        return dev;
 }
 
diff --git a/mdadm.h b/mdadm.h
index d3e88bc7fc4cf801c3b9c7ac60eb7f3130b202d1..e210718b8cb0d08530145363ff61a31aa59832ff 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -1095,7 +1095,11 @@ extern void append_metadata_update(struct supertype *st, void *buf, int len);
 extern int assemble_container_content(struct supertype *st, int mdfd,
                                      struct mdinfo *content, int runstop,
                                      char *chosen_name, int verbose);
-
+extern struct mdinfo *container_choose_spares(struct supertype *st,
+                                             unsigned long long min_size,
+                                             struct domainlist *domlist,
+                                             char *spare_group,
+                                             const char *metadata, int get_one);
 extern int add_disk(int mdfd, struct supertype *st,
                    struct mdinfo *sra, struct mdinfo *info);
 extern int remove_disk(int mdfd, struct supertype *st,
index c4100efc2a2ab0a7d3b0f9033ce2d644b716066e..dc3b03d39748f440646b6756583408ccd00b38ab 100644 (file)
@@ -6241,42 +6241,8 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
  */
 static struct mdinfo *get_spares_for_grow(struct supertype *st)
 {
-       dev_t dev = 0;
-       struct mdinfo *disks, *d, **dp;
        unsigned long long min_size = min_acceptable_spare_size_imsm(st);
-
-       /* get list of alldisks in container */
-       disks = getinfo_super_disks_imsm(st);
-
-       if (!disks)
-               return NULL;
-       /* find spare devices on the list */
-       dp = &disks->devs;
-       disks->array.spare_disks = 0;
-       while (*dp) {
-               int found = 0;
-               d = *dp;
-               if (d->disk.state == 0) {
-                       /* check if size is acceptable */
-                       unsigned long long dev_size;
-                       dev = makedev(d->disk.major,d->disk.minor);
-                       if (min_size &&
-                           dev_size_from_id(dev,  &dev_size) &&
-                           dev_size >= min_size) {
-                               dev = 0;
-                               found = 1;
-                       }
-               }
-               if (found) {
-                       dp = &d->next;
-                       disks->array.spare_disks++;
-               } else {
-                       *dp = d->next;
-                       d->next = NULL;
-                       sysfs_free(d);
-               }
-       }
-       return disks;
+       return container_choose_spares(st, min_size, NULL, NULL, NULL, 0);
 }
 
 /******************************************************************************
diff --git a/util.c b/util.c
index c4c31a315f689c3878b4cfa1cd719be054f87fe6..10d2140606124a1b9c28b36405ee6aa594a22f58 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1909,3 +1909,63 @@ int experimental(void)
        }
 }
 
+/* Pick all spares matching given criteria from a container
+ * if min_size == 0 do not check size
+ * if domlist == NULL do not check domains
+ * if spare_group given add it to domains of each spare
+ * metadata allows to test domains using metadata of destination array */
+struct mdinfo *container_choose_spares(struct supertype *st,
+                                      unsigned long long min_size,
+                                      struct domainlist *domlist,
+                                      char *spare_group,
+                                      const char *metadata, int get_one)
+{
+       struct mdinfo *d, **dp, *disks = NULL;
+
+       /* get list of all disks in container */
+       if (st->ss->getinfo_super_disks)
+               disks = st->ss->getinfo_super_disks(st);
+
+       if (!disks)
+               return disks;
+       /* find spare devices on the list */
+       dp = &disks->devs;
+       disks->array.spare_disks = 0;
+       while (*dp) {
+               int found = 0;
+               d = *dp;
+               if (d->disk.state == 0) {
+                       /* check if size is acceptable */
+                       unsigned long long dev_size;
+                       dev_t dev = makedev(d->disk.major,d->disk.minor);
+
+                       if (!min_size ||
+                          (dev_size_from_id(dev,  &dev_size) &&
+                           dev_size >= min_size))
+                               found = 1;
+                       /* check if domain matches */
+                       if (found && domlist) {
+                               struct dev_policy *pol = devnum_policy(dev);
+                               if (spare_group)
+                                       pol_add(&pol, pol_domain,
+                                               spare_group, NULL);
+                               if (!domain_test(domlist, pol, metadata))
+                                       found = 0;
+                               dev_policy_free(pol);
+                       }
+               }
+               if (found) {
+                       dp = &d->next;
+                       disks->array.spare_disks++;
+                       if (get_one) {
+                               sysfs_free(*dp);
+                               d->next = NULL;
+                       }
+               } else {
+                       *dp = d->next;
+                       d->next = NULL;
+                       sysfs_free(d);
+               }
+       }
+       return disks;
+}