]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Allow more spare selection criteria
authorAlexey Obitotskiy <aleksey.obitotskiy@intel.com>
Tue, 9 May 2017 10:25:46 +0000 (12:25 +0200)
committerJes Sorensen <jsorensen@fb.com>
Tue, 9 May 2017 18:18:36 +0000 (14:18 -0400)
Disks can be moved across containers in order to be used as a spare
drive for reubild. At the moment the only requirement checked for such
disk is its size (if it matches donor expectations). In order to
introduce more criteria rename corresponding superswitch method to more
generic name and move function parameter to a structure. This change is
a big edit but it doesn't introduce any changes in code logic, it just
updates function naming and parameters.

Signed-off-by: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
Incremental.c
Monitor.c
mdadm.h
super-intel.c
util.c

index 680d31858f98d12577731c50aece8dba0d970b23..fe9d64430c700ee27ba19969d35dc35b445c5a8e 100644 (file)
@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                struct domainlist *dl = NULL;
                struct mdinfo *sra;
                unsigned long long devsize;
-               unsigned long long component_size = 0;
+               struct spare_criteria sc = {0};
 
                if (is_subarray(mp->metadata))
                        continue;
@@ -936,7 +936,8 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                        }
                        if (st3->ss->load_container &&
                            !st3->ss->load_container(st3, mdfd, mp->path)) {
-                               component_size = st3->ss->min_acceptable_spare_size(st3);
+                               if (st3->ss->get_spare_criteria)
+                                       st3->ss->get_spare_criteria(st3, &sc);
                                st3->ss->free_super(st3);
                        }
                        free(st3);
@@ -947,7 +948,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                                         sra->devs ? sra->devs->data_offset :
                                         INVALID_SECTORS) <
                     sra->component_size) ||
-                   (sra->component_size == 0 && devsize < component_size)) {
+                   (sra->component_size == 0 && devsize < sc.min_size)) {
                        if (verbose > 1)
                                pr_err("not adding %s to %s as it is too small\n",
                                        devname, mp->path);
@@ -1624,12 +1625,15 @@ static int Incremental_container(struct supertype *st, char *devname,
                struct supertype *sst =
                        super_imsm.match_metadata_desc("imsm");
                struct mdinfo *sinfo;
-               unsigned long long min_size = 0;
-               if (st->ss->min_acceptable_spare_size)
-                       min_size = st->ss->min_acceptable_spare_size(st);
+
                if (!sst->ss->load_container(sst, sfd, NULL)) {
+                       struct spare_criteria sc = {0};
+
+                       if (st->ss->get_spare_criteria)
+                               st->ss->get_spare_criteria(st, &sc);
+
                        close(sfd);
-                       sinfo = container_choose_spares(sst, min_size,
+                       sinfo = container_choose_spares(sst, &sc,
                                                        domains, NULL,
                                                        st->ss->name, 0);
                        sst->ss->free_super(sst);
index ec643d450e6b6c4971e1471f510c4da7534b6c57..9a2baad02e1193c11228eedf0293b9d587af7e51 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -723,13 +723,14 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
        return new_found;
 }
 
-static int get_min_spare_size_required(struct state *st, unsigned long long *sizep)
+static int get_required_spare_criteria(struct state *st,
+                                      struct spare_criteria *sc)
 {
        int fd;
 
        if (!st->metadata ||
-           !st->metadata->ss->min_acceptable_spare_size) {
-               *sizep = 0;
+           !st->metadata->ss->get_spare_criteria) {
+               sc->min_size = 0;
                return 0;
        }
 
@@ -743,7 +744,8 @@ static int get_min_spare_size_required(struct state *st, unsigned long long *siz
        close(fd);
        if (!st->metadata->sb)
                return 1;
-       *sizep = st->metadata->ss->min_acceptable_spare_size(st->metadata);
+
+       st->metadata->ss->get_spare_criteria(st->metadata, sc);
        st->metadata->ss->free_super(st->metadata);
 
        return 0;
@@ -775,7 +777,7 @@ static int check_donor(struct state *from, struct state *to)
 }
 
 static dev_t choose_spare(struct state *from, struct state *to,
-                       struct domainlist *domlist, unsigned long long min_size)
+                       struct domainlist *domlist, struct spare_criteria *sc)
 {
        int d;
        dev_t dev = 0;
@@ -790,9 +792,9 @@ static dev_t choose_spare(struct state *from, struct state *to,
                            test_partition_from_id(from->devid[d]))
                                continue;
 
-                       if (min_size &&
+                       if (sc->min_size &&
                            dev_size_from_id(from->devid[d], &dev_size) &&
-                           dev_size < min_size)
+                           dev_size < sc->min_size)
                                continue;
 
                        pol = devid_policy(from->devid[d]);
@@ -809,7 +811,7 @@ static dev_t choose_spare(struct state *from, struct state *to,
 
 static dev_t container_choose_spare(struct state *from, struct state *to,
                                    struct domainlist *domlist,
-                                   unsigned long long min_size, int active)
+                                   struct spare_criteria *sc, int active)
 {
        /* This is similar to choose_spare, but we cannot trust devstate,
         * so we need to read the metadata instead
@@ -860,7 +862,7 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
        }
 
        /* We only need one spare so full list not needed */
-       list = container_choose_spares(st, min_size, domlist, from->spare_group,
+       list = container_choose_spares(st, sc, domlist, from->spare_group,
                                       to->metadata->ss->name, 1);
        if (list) {
                struct mdinfo *disks = list->devs;
@@ -876,6 +878,7 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
 {
        struct state *from;
        struct state *st;
+       struct spare_criteria sc;
 
        link_containers_with_subarrays(statelist);
        for (st = statelist; st; st = st->next)
@@ -884,7 +887,6 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
                        struct domainlist *domlist = NULL;
                        int d;
                        struct state *to = st;
-                       unsigned long long min_size;
 
                        if (to->parent_devnm[0] && !to->parent)
                                /* subarray monitored without parent container
@@ -895,14 +897,14 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
                                /* member of a container */
                                to = to->parent;
 
-                       if (get_min_spare_size_required(to, &min_size))
+                       if (get_required_spare_criteria(to, &sc))
                                continue;
                        if (to->metadata->ss->external) {
                                /* We must make sure there is
                                 * no suitable spare in container already.
                                 * If there is we don't add more */
                                dev_t devid = container_choose_spare(
-                                       to, to, NULL, min_size, st->active);
+                                       to, to, NULL, &sc, st->active);
                                if (devid > 0)
                                        continue;
                        }
@@ -925,10 +927,10 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
                                        continue;
                                if (from->metadata->ss->external)
                                        devid = container_choose_spare(
-                                               from, to, domlist, min_size, 0);
+                                               from, to, domlist, &sc, 0);
                                else
                                        devid = choose_spare(from, to, domlist,
-                                                            min_size);
+                                                            &sc);
                                if (devid > 0
                                    && move_spare(from->devname, to->devname, devid)) {
                                        alert("MoveSpare", to->devname, from->devname, info);
diff --git a/mdadm.h b/mdadm.h
index a92feb2acc8f44933105bc1ac851bc7a80c7b27d..8da7fd3e12a5dc9dd005182aa11d160b5bb5ea7b 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -361,6 +361,10 @@ struct createinfo {
        struct supertype *supertype;
 };
 
+struct spare_criteria {
+       unsigned long long min_size;
+};
+
 enum mode {
        ASSEMBLE=1,
        BUILD,
@@ -940,11 +944,13 @@ extern struct superswitch {
         */
        __u64 (*avail_size)(struct supertype *st, __u64 size,
                            unsigned long long data_offset);
-       /* This is similar to 'avail_size' in purpose, but is used for
-        * containers for which there is no 'component size' to compare.
-        * This reports that whole-device size which is a minimum
+       /*
+        * Return spare criteria for array:
+        * - minimum disk size can be used in array;
+        * Return values: 0 - for success and -EINVAL on error.
         */
-       unsigned long long (*min_acceptable_spare_size)(struct supertype *st);
+       int (*get_spare_criteria)(struct supertype *st,
+                                 struct spare_criteria *sc);
        /* Find somewhere to put a bitmap - possibly auto-size it - and
         * update the metadata to record this.  The array may be newly
         * created, in which case data_size may be updated, or it might
@@ -1507,7 +1513,7 @@ extern int assemble_container_content(struct supertype *st, int mdfd,
 #define        INCR_ALREADY    4
 #define        INCR_YES        8
 extern struct mdinfo *container_choose_spares(struct supertype *st,
-                                             unsigned long long min_size,
+                                             struct spare_criteria *criteria,
                                              struct domainlist *domlist,
                                              char *spare_group,
                                              const char *metadata, int get_one);
index e88fe82f7189fc988f05b9abf29be5c85714e997..be973f8b9e07c1caa778780b6f911a10424cea58 100644 (file)
@@ -1383,37 +1383,44 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
        return  (remainder < rv) ? remainder : rv;
 }
 
-/* Return minimum size of a spare that can be used in this array*/
-static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
+/*
+ * Return minimum size of a spare and sector size
+ * that can be used in this array
+ */
+int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
 {
        struct intel_super *super = st->sb;
        struct dl *dl;
        struct extent *e;
        int i;
-       unsigned long long rv = 0;
+       unsigned long long size = 0;
+
+       c->min_size = 0;
 
        if (!super)
-               return rv;
+               return -EINVAL;
        /* find first active disk in array */
        dl = super->disks;
        while (dl && (is_failed(&dl->disk) || dl->index == -1))
                dl = dl->next;
        if (!dl)
-               return rv;
+               return -EINVAL;
        /* find last lba used by subarrays */
        e = get_extents(super, dl);
        if (!e)
-               return rv;
+               return -EINVAL;
        for (i = 0; e[i].size; i++)
                continue;
        if (i > 0)
-               rv = e[i-1].start + e[i-1].size;
+               size = e[i-1].start + e[i-1].size;
        free(e);
 
        /* add the amount of space needed for metadata */
-       rv = rv + imsm_min_reserved_sectors(super);
+       size += imsm_min_reserved_sectors(super);
+
+       c->min_size = size * 512;
 
-       return rv * 512;
+       return 0;
 }
 
 static int is_gen_migration(struct imsm_dev *dev);
@@ -10817,8 +10824,10 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
  */
 static struct mdinfo *get_spares_for_grow(struct supertype *st)
 {
-       unsigned long long min_size = min_acceptable_spare_size_imsm(st);
-       return container_choose_spares(st, min_size, NULL, NULL, NULL, 0);
+       struct spare_criteria sc;
+
+       get_spare_criteria_imsm(st, &sc);
+       return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
 }
 
 /******************************************************************************
@@ -11853,7 +11862,7 @@ struct superswitch super_imsm = {
        .update_super   = update_super_imsm,
 
        .avail_size     = avail_size_imsm,
-       .min_acceptable_spare_size = min_acceptable_spare_size_imsm,
+       .get_spare_criteria = get_spare_criteria_imsm,
 
        .compare_super  = compare_super_imsm,
 
diff --git a/util.c b/util.c
index 11ff2ccba70e8e56bbdb550d96efcada86671b58..8b3c67ddfa3be9ad03dc01397f0aadb8e1d4cc5e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -2107,7 +2107,7 @@ int experimental(void)
  * 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 spare_criteria *criteria,
                                       struct domainlist *domlist,
                                       char *spare_group,
                                       const char *metadata, int get_one)
@@ -2131,9 +2131,9 @@ struct mdinfo *container_choose_spares(struct supertype *st,
                        unsigned long long dev_size;
                        dev_t dev = makedev(d->disk.major,d->disk.minor);
 
-                       if (!min_size ||
+                       if (!criteria->min_size ||
                           (dev_size_from_id(dev,  &dev_size) &&
-                           dev_size >= min_size))
+                           dev_size >= criteria->min_size))
                                found = 1;
                        /* check if domain matches */
                        if (found && domlist) {