]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/ceph/crush/mapper.c
crush: crush_init_workspace starts with struct crush_work
[mirror_ubuntu-bionic-kernel.git] / net / ceph / crush / mapper.c
index b5cd8c21bfdfbf4d85bd93993f1f02807c5200be..9887fce04219aae72640af9a2c82f3cb768953ab 100644 (file)
@@ -302,19 +302,42 @@ static __u64 crush_ln(unsigned int xin)
  *
  */
 
+static __u32 *get_choose_arg_weights(const struct crush_bucket_straw2 *bucket,
+                                    const struct crush_choose_arg *arg,
+                                    int position)
+{
+       if (!arg || !arg->weight_set || arg->weight_set_size == 0)
+               return bucket->item_weights;
+
+       if (position >= arg->weight_set_size)
+               position = arg->weight_set_size - 1;
+       return arg->weight_set[position].weights;
+}
+
+static __s32 *get_choose_arg_ids(const struct crush_bucket_straw2 *bucket,
+                                const struct crush_choose_arg *arg)
+{
+       if (!arg || !arg->ids)
+               return bucket->h.items;
+
+       return arg->ids;
+}
+
 static int bucket_straw2_choose(const struct crush_bucket_straw2 *bucket,
-                               int x, int r)
+                               int x, int r,
+                               const struct crush_choose_arg *arg,
+                               int position)
 {
        unsigned int i, high = 0;
        unsigned int u;
-       unsigned int w;
        __s64 ln, draw, high_draw = 0;
+       __u32 *weights = get_choose_arg_weights(bucket, arg, position);
+       __s32 *ids = get_choose_arg_ids(bucket, arg);
 
        for (i = 0; i < bucket->h.size; i++) {
-               w = bucket->item_weights[i];
-               if (w) {
-                       u = crush_hash32_3(bucket->h.hash, x,
-                                          bucket->h.items[i], r);
+               dprintk("weight 0x%x item %d\n", weights[i], ids[i]);
+               if (weights[i]) {
+                       u = crush_hash32_3(bucket->h.hash, x, ids[i], r);
                        u &= 0xffff;
 
                        /*
@@ -335,7 +358,7 @@ static int bucket_straw2_choose(const struct crush_bucket_straw2 *bucket,
                         * weight means a larger (less negative) value
                         * for draw.
                         */
-                       draw = div64_s64(ln, w);
+                       draw = div64_s64(ln, weights[i]);
                } else {
                        draw = S64_MIN;
                }
@@ -352,7 +375,9 @@ static int bucket_straw2_choose(const struct crush_bucket_straw2 *bucket,
 
 static int crush_bucket_choose(const struct crush_bucket *in,
                               struct crush_work_bucket *work,
-                              int x, int r)
+                              int x, int r,
+                              const struct crush_choose_arg *arg,
+                              int position)
 {
        dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r);
        BUG_ON(in->size == 0);
@@ -374,7 +399,7 @@ static int crush_bucket_choose(const struct crush_bucket *in,
        case CRUSH_BUCKET_STRAW2:
                return bucket_straw2_choose(
                        (const struct crush_bucket_straw2 *)in,
-                       x, r);
+                       x, r, arg, position);
        default:
                dprintk("unknown bucket %d alg %d\n", in->id, in->alg);
                return in->items[0];
@@ -436,7 +461,8 @@ static int crush_choose_firstn(const struct crush_map *map,
                               unsigned int vary_r,
                               unsigned int stable,
                               int *out2,
-                              int parent_r)
+                              int parent_r,
+                              const struct crush_choose_arg *choose_args)
 {
        int rep;
        unsigned int ftotal, flocal;
@@ -486,7 +512,10 @@ static int crush_choose_firstn(const struct crush_map *map,
                                else
                                        item = crush_bucket_choose(
                                                in, work->work[-1-in->id],
-                                               x, r);
+                                               x, r,
+                                               (choose_args ?
+                                                &choose_args[-1-in->id] : 0),
+                                               outpos);
                                if (item >= map->max_devices) {
                                        dprintk("   bad item %d\n", item);
                                        skip_rep = 1;
@@ -543,7 +572,8 @@ static int crush_choose_firstn(const struct crush_map *map,
                                                            vary_r,
                                                            stable,
                                                            NULL,
-                                                           sub_r) <= outpos)
+                                                           sub_r,
+                                                           choose_args) <= outpos)
                                                        /* didn't get leaf */
                                                        reject = 1;
                                        } else {
@@ -620,7 +650,8 @@ static void crush_choose_indep(const struct crush_map *map,
                               unsigned int recurse_tries,
                               int recurse_to_leaf,
                               int *out2,
-                              int parent_r)
+                              int parent_r,
+                              const struct crush_choose_arg *choose_args)
 {
        const struct crush_bucket *in = bucket;
        int endpos = outpos + left;
@@ -692,7 +723,10 @@ static void crush_choose_indep(const struct crush_map *map,
 
                                item = crush_bucket_choose(
                                        in, work->work[-1-in->id],
-                                       x, r);
+                                       x, r,
+                                       (choose_args ?
+                                        &choose_args[-1-in->id] : 0),
+                                       outpos);
                                if (item >= map->max_devices) {
                                        dprintk("   bad item %d\n", item);
                                        out[rep] = CRUSH_ITEM_NONE;
@@ -746,7 +780,8 @@ static void crush_choose_indep(const struct crush_map *map,
                                                        x, 1, numrep, 0,
                                                        out2, rep,
                                                        recurse_tries, 0,
-                                                       0, NULL, r);
+                                                       0, NULL, r,
+                                                       choose_args);
                                                if (out2[rep] == CRUSH_ITEM_NONE) {
                                                        /* placed nothing; no leaf */
                                                        break;
@@ -823,7 +858,7 @@ void crush_init_workspace(const struct crush_map *map, void *v)
         * set the pointer first and then reserve the space for it to
         * point to by incrementing the point.
         */
-       v += sizeof(struct crush_work *);
+       v += sizeof(struct crush_work);
        w->work = v;
        v += map->max_buckets * sizeof(struct crush_work_bucket *);
        for (b = 0; b < map->max_buckets; ++b) {
@@ -854,11 +889,12 @@ void crush_init_workspace(const struct crush_map *map, void *v)
  * @weight: weight vector (for map leaves)
  * @weight_max: size of weight vector
  * @cwin: pointer to at least crush_work_size() bytes of memory
+ * @choose_args: weights and ids for each known bucket
  */
 int crush_do_rule(const struct crush_map *map,
                  int ruleno, int x, int *result, int result_max,
                  const __u32 *weight, int weight_max,
-                 void *cwin)
+                 void *cwin, const struct crush_choose_arg *choose_args)
 {
        int result_len;
        struct crush_work *cw = cwin;
@@ -1013,7 +1049,8 @@ int crush_do_rule(const struct crush_map *map,
                                                vary_r,
                                                stable,
                                                c+osize,
-                                               0);
+                                               0,
+                                               choose_args);
                                } else {
                                        out_size = ((numrep < (result_max-osize)) ?
                                                    numrep : (result_max-osize));
@@ -1030,7 +1067,8 @@ int crush_do_rule(const struct crush_map *map,
                                                   choose_leaf_tries : 1,
                                                recurse_to_leaf,
                                                c+osize,
-                                               0);
+                                               0,
+                                               choose_args);
                                        osize += out_size;
                                }
                        }