summaryrefslogtreecommitdiff
path: root/fs/ceph/crush
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-10-07 21:59:34 +0400
committerSage Weil <sage@newdream.net>2009-10-07 21:59:34 +0400
commitb28813a61d6ffe05ad353a86965607bb7a7fd60f (patch)
treef416befcd63c5b93b227df4280afb18e00335c27 /fs/ceph/crush
parentb195befd9acb514dd2afb722e63fdd880ed63217 (diff)
downloadlinux-b28813a61d6ffe05ad353a86965607bb7a7fd60f.tar.xz
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.c9
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,
struct crush_bucket *in = bucket;
int r;
int i;
- int item;
+ int item = 0;
int itemtype;
int collide, reject;
const int orig_tries = 5; /* attempts before we fall back to search */
@@ -316,6 +316,7 @@ static int crush_choose(struct crush_map *map,
/* choose through intervening buckets */
flocal = 0;
do {
+ collide = 0;
retry_bucket = 0;
r = rep;
if (in->alg == CRUSH_BUCKET_UNIFORM) {
@@ -340,6 +341,10 @@ static int crush_choose(struct crush_map *map,
}
/* bucket choose */
+ if (in->size == 0) {
+ reject = 1;
+ goto reject;
+ }
if (flocal >= (in->size>>1) &&
flocal > orig_tries)
item = bucket_perm_choose(in, x, r);
@@ -363,7 +368,6 @@ static int crush_choose(struct crush_map *map,
}
/* collision? */
- collide = 0;
for (i = 0; i < outpos; i++) {
if (out[i] == item) {
collide = 1;
@@ -388,6 +392,7 @@ static int crush_choose(struct crush_map *map,
reject = 0;
}
+reject:
if (reject || collide) {
ftotal++;
flocal++;