Commit 3ca9f5f9 authored by Ilya Dryomov's avatar Ilya Dryomov Committed by Sasha Levin

crush: ensuring at most num-rep osds are selected

[ Upstream commit 45002267 ]

Crush temporary buffers are allocated as per replica size configured
by the user.  When there are more final osds (to be selected as per
rule) than the replicas, buffer overlaps and it causes crash.  Now, it
ensures that at most num-rep osds are selected even if more number of
osds are allowed by the rule.

Reflects ceph.git commits 6b4d1aa99718e3b367496326c1e64551330fabc0,
                          234b066ba04976783d15ff2abc3e81b6cc06fb10.
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent b824a7f0
...@@ -290,6 +290,7 @@ static int is_out(const struct crush_map *map, ...@@ -290,6 +290,7 @@ static int is_out(const struct crush_map *map,
* @type: the type of item to choose * @type: the type of item to choose
* @out: pointer to output vector * @out: pointer to output vector
* @outpos: our position in that vector * @outpos: our position in that vector
* @out_size: size of the out vector
* @tries: number of attempts to make * @tries: number of attempts to make
* @recurse_tries: number of attempts to have recursive chooseleaf make * @recurse_tries: number of attempts to have recursive chooseleaf make
* @local_retries: localized retries * @local_retries: localized retries
...@@ -304,6 +305,7 @@ static int crush_choose_firstn(const struct crush_map *map, ...@@ -304,6 +305,7 @@ static int crush_choose_firstn(const struct crush_map *map,
const __u32 *weight, int weight_max, const __u32 *weight, int weight_max,
int x, int numrep, int type, int x, int numrep, int type,
int *out, int outpos, int *out, int outpos,
int out_size,
unsigned int tries, unsigned int tries,
unsigned int recurse_tries, unsigned int recurse_tries,
unsigned int local_retries, unsigned int local_retries,
...@@ -322,6 +324,7 @@ static int crush_choose_firstn(const struct crush_map *map, ...@@ -322,6 +324,7 @@ static int crush_choose_firstn(const struct crush_map *map,
int item = 0; int item = 0;
int itemtype; int itemtype;
int collide, reject; int collide, reject;
int count = out_size;
dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d tries %d recurse_tries %d local_retries %d local_fallback_retries %d parent_r %d\n", dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d tries %d recurse_tries %d local_retries %d local_fallback_retries %d parent_r %d\n",
recurse_to_leaf ? "_LEAF" : "", recurse_to_leaf ? "_LEAF" : "",
...@@ -329,7 +332,7 @@ static int crush_choose_firstn(const struct crush_map *map, ...@@ -329,7 +332,7 @@ static int crush_choose_firstn(const struct crush_map *map,
tries, recurse_tries, local_retries, local_fallback_retries, tries, recurse_tries, local_retries, local_fallback_retries,
parent_r); parent_r);
for (rep = outpos; rep < numrep; rep++) { for (rep = outpos; rep < numrep && count > 0 ; rep++) {
/* keep trying until we get a non-out, non-colliding item */ /* keep trying until we get a non-out, non-colliding item */
ftotal = 0; ftotal = 0;
skip_rep = 0; skip_rep = 0;
...@@ -403,7 +406,7 @@ static int crush_choose_firstn(const struct crush_map *map, ...@@ -403,7 +406,7 @@ static int crush_choose_firstn(const struct crush_map *map,
map->buckets[-1-item], map->buckets[-1-item],
weight, weight_max, weight, weight_max,
x, outpos+1, 0, x, outpos+1, 0,
out2, outpos, out2, outpos, count,
recurse_tries, 0, recurse_tries, 0,
local_retries, local_retries,
local_fallback_retries, local_fallback_retries,
...@@ -463,6 +466,7 @@ static int crush_choose_firstn(const struct crush_map *map, ...@@ -463,6 +466,7 @@ static int crush_choose_firstn(const struct crush_map *map,
dprintk("CHOOSE got %d\n", item); dprintk("CHOOSE got %d\n", item);
out[outpos] = item; out[outpos] = item;
outpos++; outpos++;
count--;
} }
dprintk("CHOOSE returns %d\n", outpos); dprintk("CHOOSE returns %d\n", outpos);
...@@ -654,6 +658,7 @@ int crush_do_rule(const struct crush_map *map, ...@@ -654,6 +658,7 @@ int crush_do_rule(const struct crush_map *map,
__u32 step; __u32 step;
int i, j; int i, j;
int numrep; int numrep;
int out_size;
/* /*
* the original choose_total_tries value was off by one (it * the original choose_total_tries value was off by one (it
* counted "retries" and not "tries"). add one. * counted "retries" and not "tries"). add one.
...@@ -761,6 +766,7 @@ int crush_do_rule(const struct crush_map *map, ...@@ -761,6 +766,7 @@ int crush_do_rule(const struct crush_map *map,
x, numrep, x, numrep,
curstep->arg2, curstep->arg2,
o+osize, j, o+osize, j,
result_max-osize,
choose_tries, choose_tries,
recurse_tries, recurse_tries,
choose_local_retries, choose_local_retries,
...@@ -770,11 +776,13 @@ int crush_do_rule(const struct crush_map *map, ...@@ -770,11 +776,13 @@ int crush_do_rule(const struct crush_map *map,
c+osize, c+osize,
0); 0);
} else { } else {
out_size = ((numrep < (result_max-osize)) ?
numrep : (result_max-osize));
crush_choose_indep( crush_choose_indep(
map, map,
map->buckets[-1-w[i]], map->buckets[-1-w[i]],
weight, weight_max, weight, weight_max,
x, numrep, numrep, x, out_size, numrep,
curstep->arg2, curstep->arg2,
o+osize, j, o+osize, j,
choose_tries, choose_tries,
...@@ -783,7 +791,7 @@ int crush_do_rule(const struct crush_map *map, ...@@ -783,7 +791,7 @@ int crush_do_rule(const struct crush_map *map,
recurse_to_leaf, recurse_to_leaf,
c+osize, c+osize,
0); 0);
osize += numrep; osize += out_size;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment