extern int crush_do_rule(const struct crush_map *map,
                         int ruleno,
                         int x, int *result, int result_max,
-                        const __u32 *weights, int weight_max);
+                        const __u32 *weights, int weight_max,
+                        int *scratch);
 
 #endif
 
  * @result_max: maximum result size
  * @weight: weight vector (for map leaves)
  * @weight_max: size of weight vector
+ * @scratch: scratch vector for private use; must be >= 3 * result_max
  */
 int crush_do_rule(const struct crush_map *map,
                  int ruleno, int x, int *result, int result_max,
-                 const __u32 *weight, int weight_max)
+                 const __u32 *weight, int weight_max,
+                 int *scratch)
 {
        int result_len;
-       int a[CRUSH_MAX_SET];
-       int b[CRUSH_MAX_SET];
-       int c[CRUSH_MAX_SET];
+       int *a = scratch;
+       int *b = scratch + result_max;
+       int *c = scratch + result_max*2;
        int recurse_to_leaf;
        int *w;
        int wsize = 0;
 
 }
 EXPORT_SYMBOL(ceph_calc_ceph_pg);
 
+static int crush_do_rule_ary(const struct crush_map *map, int ruleno, int x,
+                            int *result, int result_max,
+                            const __u32 *weight, int weight_max)
+{
+       int scratch[result_max * 3];
+
+       return crush_do_rule(map, ruleno, x, result, result_max,
+                            weight, weight_max, scratch);
+}
+
 /*
  * Calculate raw osd vector for the given pgid.  Return pointer to osd
  * array, or NULL on failure.
                                      pool->pgp_num_mask) +
                        (unsigned)pgid.pool;
        }
-       r = crush_do_rule(osdmap->crush, ruleno, pps, osds,
-                         min_t(int, pool->size, *num),
-                         osdmap->osd_weight, osdmap->max_osd);
+       r = crush_do_rule_ary(osdmap->crush, ruleno, pps,
+                             osds, min_t(int, pool->size, *num),
+                             osdmap->osd_weight, osdmap->max_osd);
        if (r < 0) {
                pr_err("error %d from crush rule: pool %lld ruleset %d type %d"
                       " size %d\n", r, pgid.pool, pool->crush_ruleset,