diff options
author | Sage Weil <sage@newdream.net> | 2009-10-07 13:59:34 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-10-07 13:59:34 -0400 |
commit | b28813a61d6ffe05ad353a86965607bb7a7fd60f (patch) | |
tree | f416befcd63c5b93b227df4280afb18e00335c27 /fs/ceph/crush | |
parent | b195befd9acb514dd2afb722e63fdd880ed63217 (diff) |
ceph: gracefully avoid empty crush buckets
This avoids a divide by zero when the input and/or map are
malformed.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/crush')
-rw-r--r-- | fs/ceph/crush/mapper.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/ceph/crush/mapper.c b/fs/ceph/crush/mapper.c index 0f0730c62695..c268393adfcb 100644 --- a/fs/ceph/crush/mapper.c +++ b/fs/ceph/crush/mapper.c | |||
@@ -299,7 +299,7 @@ static int crush_choose(struct crush_map *map, | |||
299 | struct crush_bucket *in = bucket; | 299 | struct crush_bucket *in = bucket; |
300 | int r; | 300 | int r; |
301 | int i; | 301 | int i; |
302 | int item; | 302 | int item = 0; |
303 | int itemtype; | 303 | int itemtype; |
304 | int collide, reject; | 304 | int collide, reject; |
305 | const int orig_tries = 5; /* attempts before we fall back to search */ | 305 | const int orig_tries = 5; /* attempts before we fall back to search */ |
@@ -316,6 +316,7 @@ static int crush_choose(struct crush_map *map, | |||
316 | /* choose through intervening buckets */ | 316 | /* choose through intervening buckets */ |
317 | flocal = 0; | 317 | flocal = 0; |
318 | do { | 318 | do { |
319 | collide = 0; | ||
319 | retry_bucket = 0; | 320 | retry_bucket = 0; |
320 | r = rep; | 321 | r = rep; |
321 | if (in->alg == CRUSH_BUCKET_UNIFORM) { | 322 | if (in->alg == CRUSH_BUCKET_UNIFORM) { |
@@ -340,6 +341,10 @@ static int crush_choose(struct crush_map *map, | |||
340 | } | 341 | } |
341 | 342 | ||
342 | /* bucket choose */ | 343 | /* bucket choose */ |
344 | if (in->size == 0) { | ||
345 | reject = 1; | ||
346 | goto reject; | ||
347 | } | ||
343 | if (flocal >= (in->size>>1) && | 348 | if (flocal >= (in->size>>1) && |
344 | flocal > orig_tries) | 349 | flocal > orig_tries) |
345 | item = bucket_perm_choose(in, x, r); | 350 | item = bucket_perm_choose(in, x, r); |
@@ -363,7 +368,6 @@ static int crush_choose(struct crush_map *map, | |||
363 | } | 368 | } |
364 | 369 | ||
365 | /* collision? */ | 370 | /* collision? */ |
366 | collide = 0; | ||
367 | for (i = 0; i < outpos; i++) { | 371 | for (i = 0; i < outpos; i++) { |
368 | if (out[i] == item) { | 372 | if (out[i] == item) { |
369 | collide = 1; | 373 | collide = 1; |
@@ -388,6 +392,7 @@ static int crush_choose(struct crush_map *map, | |||
388 | reject = 0; | 392 | reject = 0; |
389 | } | 393 | } |
390 | 394 | ||
395 | reject: | ||
391 | if (reject || collide) { | 396 | if (reject || collide) { |
392 | ftotal++; | 397 | ftotal++; |
393 | flocal++; | 398 | flocal++; |