diff options
author | Sage Weil <sage@newdream.net> | 2009-10-07 21:59:34 +0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-10-07 21:59:34 +0400 |
commit | b28813a61d6ffe05ad353a86965607bb7a7fd60f (patch) | |
tree | f416befcd63c5b93b227df4280afb18e00335c27 | |
parent | b195befd9acb514dd2afb722e63fdd880ed63217 (diff) | |
download | linux-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>
-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, 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++; |