diff options
| author | Sage Weil <sage@newdream.net> | 2010-06-24 15:58:14 -0400 |
|---|---|---|
| committer | Sage Weil <sage@newdream.net> | 2010-06-24 15:58:14 -0400 |
| commit | a1a31e734241aefcb2b30fb0cc0376977b6d2ba8 (patch) | |
| tree | 3247b61cf5f1cc3efb212e0362493f98f326e4ff | |
| parent | 55bda7aacd13f5fdfeaafc16934953171405c692 (diff) | |
ceph: fix crush CHOOSE_LEAF when type is already a leaf
We may not recurse for CHOOSE_LEAF if we start with a leaf node. When
that happens, the out2 vector needs to be filled in with the result.
Signed-off-by: Sage Weil <sage@newdream.net>
| -rw-r--r-- | fs/ceph/crush/mapper.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/fs/ceph/crush/mapper.c b/fs/ceph/crush/mapper.c index 804e6d53b77c..374266bddd9c 100644 --- a/fs/ceph/crush/mapper.c +++ b/fs/ceph/crush/mapper.c | |||
| @@ -238,7 +238,7 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket, | |||
| 238 | 238 | ||
| 239 | static int crush_bucket_choose(struct crush_bucket *in, int x, int r) | 239 | static int crush_bucket_choose(struct crush_bucket *in, int x, int r) |
| 240 | { | 240 | { |
| 241 | dprintk("choose %d x=%d r=%d\n", in->id, x, r); | 241 | dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r); |
| 242 | switch (in->alg) { | 242 | switch (in->alg) { |
| 243 | case CRUSH_BUCKET_UNIFORM: | 243 | case CRUSH_BUCKET_UNIFORM: |
| 244 | return bucket_uniform_choose((struct crush_bucket_uniform *)in, | 244 | return bucket_uniform_choose((struct crush_bucket_uniform *)in, |
| @@ -305,7 +305,9 @@ static int crush_choose(struct crush_map *map, | |||
| 305 | int itemtype; | 305 | int itemtype; |
| 306 | int collide, reject; | 306 | int collide, reject; |
| 307 | const int orig_tries = 5; /* attempts before we fall back to search */ | 307 | const int orig_tries = 5; /* attempts before we fall back to search */ |
| 308 | dprintk("choose bucket %d x %d outpos %d\n", bucket->id, x, outpos); | 308 | |
| 309 | dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", | ||
| 310 | bucket->id, x, outpos, numrep); | ||
| 309 | 311 | ||
| 310 | for (rep = outpos; rep < numrep; rep++) { | 312 | for (rep = outpos; rep < numrep; rep++) { |
| 311 | /* keep trying until we get a non-out, non-colliding item */ | 313 | /* keep trying until we get a non-out, non-colliding item */ |
| @@ -378,15 +380,25 @@ static int crush_choose(struct crush_map *map, | |||
| 378 | } | 380 | } |
| 379 | } | 381 | } |
| 380 | 382 | ||
| 381 | if (recurse_to_leaf && | 383 | reject = 0; |
| 382 | item < 0 && | 384 | if (recurse_to_leaf) { |
| 383 | crush_choose(map, map->buckets[-1-item], | 385 | if (item < 0) { |
| 384 | weight, | 386 | if (crush_choose(map, |
| 385 | x, outpos+1, 0, | 387 | map->buckets[-1-item], |
| 386 | out2, outpos, | 388 | weight, |
| 387 | firstn, 0, NULL) <= outpos) { | 389 | x, outpos+1, 0, |
| 388 | reject = 1; | 390 | out2, outpos, |
| 389 | } else { | 391 | firstn, 0, |
| 392 | NULL) <= outpos) | ||
| 393 | /* didn't get leaf */ | ||
| 394 | reject = 1; | ||
| 395 | } else { | ||
| 396 | /* we already have a leaf! */ | ||
| 397 | out2[outpos] = item; | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | if (!reject) { | ||
| 390 | /* out? */ | 402 | /* out? */ |
| 391 | if (itemtype == 0) | 403 | if (itemtype == 0) |
| 392 | reject = is_out(map, weight, | 404 | reject = is_out(map, weight, |
| @@ -425,12 +437,12 @@ reject: | |||
| 425 | continue; | 437 | continue; |
| 426 | } | 438 | } |
| 427 | 439 | ||
| 428 | dprintk("choose got %d\n", item); | 440 | dprintk("CHOOSE got %d\n", item); |
| 429 | out[outpos] = item; | 441 | out[outpos] = item; |
| 430 | outpos++; | 442 | outpos++; |
| 431 | } | 443 | } |
| 432 | 444 | ||
| 433 | dprintk("choose returns %d\n", outpos); | 445 | dprintk("CHOOSE returns %d\n", outpos); |
| 434 | return outpos; | 446 | return outpos; |
| 435 | } | 447 | } |
| 436 | 448 | ||
