]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ceph/crush/mapper.c
Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[karo-tx-linux.git] / net / ceph / crush / mapper.c
index 77b7a73e65cfc9845bfb6a93507ed3ad55934333..b703790b4e44788e109bb91ab61f272015000654 100644 (file)
@@ -282,7 +282,7 @@ static int is_out(const struct crush_map *map,
 }
 
 /**
- * crush_choose - choose numrep distinct items of given type
+ * crush_choose_firstn - choose numrep distinct items of given type
  * @map: the crush_map
  * @bucket: the bucket we are choose an item from
  * @x: crush input value
@@ -290,18 +290,24 @@ static int is_out(const struct crush_map *map,
  * @type: the type of item to choose
  * @out: pointer to output vector
  * @outpos: our position in that vector
- * @firstn: true if choosing "first n" items, false if choosing "indep"
- * @recurse_to_leaf: true if we want one device under each item of given type
- * @descend_once: true if we should only try one descent before giving up
+ * @tries: number of attempts to make
+ * @recurse_tries: number of attempts to have recursive chooseleaf make
+ * @local_tries: localized retries
+ * @local_fallback_tries: localized fallback retries
+ * @recurse_to_leaf: true if we want one device under each item of given type (chooseleaf instead of choose)
  * @out2: second output vector for leaf items (if @recurse_to_leaf)
  */
-static int crush_choose(const struct crush_map *map,
-                       struct crush_bucket *bucket,
-                       const __u32 *weight, int weight_max,
-                       int x, int numrep, int type,
-                       int *out, int outpos,
-                       int firstn, int recurse_to_leaf,
-                       int descend_once, int *out2)
+static int crush_choose_firstn(const struct crush_map *map,
+                              struct crush_bucket *bucket,
+                              const __u32 *weight, int weight_max,
+                              int x, int numrep, int type,
+                              int *out, int outpos,
+                              unsigned int tries,
+                              unsigned int recurse_tries,
+                              unsigned int local_tries,
+                              unsigned int local_fallback_tries,
+                              int recurse_to_leaf,
+                              int *out2)
 {
        int rep;
        unsigned int ftotal, flocal;
@@ -330,35 +336,17 @@ static int crush_choose(const struct crush_map *map,
                                collide = 0;
                                retry_bucket = 0;
                                r = rep;
-                               if (in->alg == CRUSH_BUCKET_UNIFORM) {
-                                       /* be careful */
-                                       if (firstn || (__u32)numrep >= in->size)
-                                               /* r' = r + f_total */
-                                               r += ftotal;
-                                       else if (in->size % numrep == 0)
-                                               /* r'=r+(n+1)*f_local */
-                                               r += (numrep+1) *
-                                                       (flocal+ftotal);
-                                       else
-                                               /* r' = r + n*f_local */
-                                               r += numrep * (flocal+ftotal);
-                               } else {
-                                       if (firstn)
-                                               /* r' = r + f_total */
-                                               r += ftotal;
-                                       else
-                                               /* r' = r + n*f_local */
-                                               r += numrep * (flocal+ftotal);
-                               }
+                               /* r' = r + f_total */
+                               r += ftotal;
 
                                /* bucket choose */
                                if (in->size == 0) {
                                        reject = 1;
                                        goto reject;
                                }
-                               if (map->choose_local_fallback_tries > 0 &&
+                               if (local_fallback_tries > 0 &&
                                    flocal >= (in->size>>1) &&
-                                   flocal > map->choose_local_fallback_tries)
+                                   flocal > local_fallback_tries)
                                        item = bucket_perm_choose(in, x, r);
                                else
                                        item = crush_bucket_choose(in, x, r);
@@ -399,13 +387,15 @@ static int crush_choose(const struct crush_map *map,
                                reject = 0;
                                if (!collide && recurse_to_leaf) {
                                        if (item < 0) {
-                                               if (crush_choose(map,
+                                               if (crush_choose_firstn(map,
                                                         map->buckets[-1-item],
                                                         weight, weight_max,
                                                         x, outpos+1, 0,
                                                         out2, outpos,
-                                                        firstn, 0,
-                                                        map->chooseleaf_descend_once,
+                                                        recurse_tries, 0,
+                                                        local_tries,
+                                                        local_fallback_tries,
+                                                        0,
                                                         NULL) <= outpos)
                                                        /* didn't get leaf */
                                                        reject = 1;
@@ -430,17 +420,14 @@ reject:
                                        ftotal++;
                                        flocal++;
 
-                                       if (reject && descend_once)
-                                               /* let outer call try again */
-                                               skip_rep = 1;
-                                       else if (collide && flocal <= map->choose_local_tries)
+                                       if (collide && flocal <= local_tries)
                                                /* retry locally a few times */
                                                retry_bucket = 1;
-                                       else if (map->choose_local_fallback_tries > 0 &&
-                                                flocal <= in->size + map->choose_local_fallback_tries)
+                                       else if (local_fallback_tries > 0 &&
+                                                flocal <= in->size + local_fallback_tries)
                                                /* exhaustive bucket search */
                                                retry_bucket = 1;
-                                       else if (ftotal <= map->choose_total_tries)
+                                       else if (ftotal <= tries)
                                                /* then retry descent */
                                                retry_descent = 1;
                                        else
@@ -455,12 +442,8 @@ reject:
                } while (retry_descent);
 
                if (skip_rep) {
-                       if (firstn) {
-                               dprintk("skip rep\n");
-                               continue;
-                       }
-                       dprintk("undef rep, continuing\n");
-                       item = CRUSH_ITEM_UNDEF;
+                       dprintk("skip rep\n");
+                       continue;
                }
 
                dprintk("CHOOSE got %d\n", item);
@@ -474,19 +457,22 @@ reject:
 
 
 /**
- * choose indep: alternative breadth-first positionally stable mapping
+ * crush_choose_indep: alternative breadth-first positionally stable mapping
  *
  */
 static void crush_choose_indep(const struct crush_map *map,
-                             struct crush_bucket *bucket,
-                             const __u32 *weight, int weight_max,
-                             int x, int numrep, int type,
-                             int *out, int outpos,
-                             int recurse_to_leaf,
-                             int *out2)
+                              struct crush_bucket *bucket,
+                              const __u32 *weight, int weight_max,
+                              int x, int left, int numrep, int type,
+                              int *out, int outpos,
+                              unsigned int tries,
+                              unsigned int recurse_tries,
+                              int recurse_to_leaf,
+                              int *out2,
+                              int parent_r)
 {
        struct crush_bucket *in = bucket;
-       int left = numrep - outpos;
+       int endpos = outpos + left;
        int rep;
        unsigned int ftotal;
        int r;
@@ -499,14 +485,14 @@ static void crush_choose_indep(const struct crush_map *map,
                bucket->id, x, outpos, numrep);
 
        /* initially my result is undefined */
-       for (rep = outpos; rep < numrep; rep++) {
+       for (rep = outpos; rep < endpos; rep++) {
                out[rep] = CRUSH_ITEM_UNDEF;
                if (out2)
                        out2[rep] = CRUSH_ITEM_UNDEF;
        }
 
-       for (ftotal = 0; left > 0 && ftotal < map->choose_total_tries; ftotal++) {
-               for (rep = outpos; rep < numrep; rep++) {
+       for (ftotal = 0; left > 0 && ftotal < tries; ftotal++) {
+               for (rep = outpos; rep < endpos; rep++) {
                        if (out[rep] != CRUSH_ITEM_UNDEF)
                                continue;
 
@@ -522,7 +508,7 @@ static void crush_choose_indep(const struct crush_map *map,
                                 * this will involve more devices in data
                                 * movement and tend to distribute the load.
                                 */
-                               r = rep;
+                               r = rep + parent_r;
 
                                /* be careful */
                                if (in->alg == CRUSH_BUCKET_UNIFORM &&
@@ -574,7 +560,7 @@ static void crush_choose_indep(const struct crush_map *map,
 
                                /* collision? */
                                collide = 0;
-                               for (i = outpos; i < numrep; i++) {
+                               for (i = outpos; i < endpos; i++) {
                                        if (out[i] == item) {
                                                collide = 1;
                                                break;
@@ -586,11 +572,12 @@ static void crush_choose_indep(const struct crush_map *map,
                                if (recurse_to_leaf) {
                                        if (item < 0) {
                                                crush_choose_indep(map,
-                                                                  map->buckets[-1-item],
-                                                                  weight, weight_max,
-                                                                  x, rep+1, 0,
-                                                                  out2, rep,
-                                                                  0, NULL);
+                                                  map->buckets[-1-item],
+                                                  weight, weight_max,
+                                                  x, 1, numrep, 0,
+                                                  out2, rep,
+                                                  recurse_tries, 0,
+                                                  0, NULL, r);
                                                if (out2[rep] == CRUSH_ITEM_NONE) {
                                                        /* placed nothing; no leaf */
                                                        break;
@@ -613,7 +600,7 @@ static void crush_choose_indep(const struct crush_map *map,
                        }
                }
        }
-       for (rep = outpos; rep < numrep; rep++) {
+       for (rep = outpos; rep < endpos; rep++) {
                if (out[rep] == CRUSH_ITEM_UNDEF) {
                        out[rep] = CRUSH_ITEM_NONE;
                }
@@ -653,7 +640,10 @@ int crush_do_rule(const struct crush_map *map,
        __u32 step;
        int i, j;
        int numrep;
-       const int descend_once = 0;
+       int choose_tries = map->choose_total_tries;
+       int choose_local_tries = map->choose_local_tries;
+       int choose_local_fallback_tries = map->choose_local_fallback_tries;
+       int choose_leaf_tries = 0;
 
        if ((__u32)ruleno >= map->max_rules) {
                dprintk(" bad ruleno %d\n", ruleno);
@@ -675,20 +665,40 @@ int crush_do_rule(const struct crush_map *map,
                        wsize = 1;
                        break;
 
-               case CRUSH_RULE_CHOOSE_LEAF_FIRSTN:
+               case CRUSH_RULE_SET_CHOOSE_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_SET_CHOOSELEAF_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_leaf_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_local_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_local_fallback_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_CHOOSELEAF_FIRSTN:
                case CRUSH_RULE_CHOOSE_FIRSTN:
                        firstn = 1;
                        /* fall through */
-               case CRUSH_RULE_CHOOSE_LEAF_INDEP:
+               case CRUSH_RULE_CHOOSELEAF_INDEP:
                case CRUSH_RULE_CHOOSE_INDEP:
                        if (wsize == 0)
                                break;
 
                        recurse_to_leaf =
                                curstep->op ==
-                                CRUSH_RULE_CHOOSE_LEAF_FIRSTN ||
+                                CRUSH_RULE_CHOOSELEAF_FIRSTN ||
                                curstep->op ==
-                               CRUSH_RULE_CHOOSE_LEAF_INDEP;
+                               CRUSH_RULE_CHOOSELEAF_INDEP;
 
                        /* reset output */
                        osize = 0;
@@ -707,24 +717,41 @@ int crush_do_rule(const struct crush_map *map,
                                }
                                j = 0;
                                if (firstn) {
-                                       osize += crush_choose(map,
-                                                             map->buckets[-1-w[i]],
-                                                             weight, weight_max,
-                                                             x, numrep,
-                                                             curstep->arg2,
-                                                             o+osize, j,
-                                                             firstn,
-                                                             recurse_to_leaf,
-                                                             descend_once, c+osize);
+                                       int recurse_tries;
+                                       if (choose_leaf_tries)
+                                               recurse_tries =
+                                                       choose_leaf_tries;
+                                       else if (map->chooseleaf_descend_once)
+                                               recurse_tries = 1;
+                                       else
+                                               recurse_tries = choose_tries;
+                                       osize += crush_choose_firstn(
+                                               map,
+                                               map->buckets[-1-w[i]],
+                                               weight, weight_max,
+                                               x, numrep,
+                                               curstep->arg2,
+                                               o+osize, j,
+                                               choose_tries,
+                                               recurse_tries,
+                                               choose_local_tries,
+                                               choose_local_fallback_tries,
+                                               recurse_to_leaf,
+                                               c+osize);
                                } else {
-                                       crush_choose_indep(map,
-                                                          map->buckets[-1-w[i]],
-                                                          weight, weight_max,
-                                                          x, numrep,
-                                                          curstep->arg2,
-                                                          o+osize, j,
-                                                          recurse_to_leaf,
-                                                          c+osize);
+                                       crush_choose_indep(
+                                               map,
+                                               map->buckets[-1-w[i]],
+                                               weight, weight_max,
+                                               x, numrep, numrep,
+                                               curstep->arg2,
+                                               o+osize, j,
+                                               choose_tries,
+                                               choose_leaf_tries ?
+                                                  choose_leaf_tries : 1,
+                                               recurse_to_leaf,
+                                               c+osize,
+                                               0);
                                        osize += numrep;
                                }
                        }