diff options
-rw-r--r-- | include/linux/crush/crush.h | 3 | ||||
-rw-r--r-- | net/ceph/crush/mapper.c | 172 |
2 files changed, 165 insertions, 10 deletions
diff --git a/include/linux/crush/crush.h b/include/linux/crush/crush.h index 3d6a12928560..4023b1b52296 100644 --- a/include/linux/crush/crush.h +++ b/include/linux/crush/crush.h | |||
@@ -22,7 +22,8 @@ | |||
22 | #define CRUSH_MAX_DEPTH 10 /* max crush hierarchy depth */ | 22 | #define CRUSH_MAX_DEPTH 10 /* max crush hierarchy depth */ |
23 | 23 | ||
24 | 24 | ||
25 | #define CRUSH_ITEM_UNDEF 0x7fffffff /* undefined result */ | 25 | #define CRUSH_ITEM_UNDEF 0x7ffffffe /* undefined result (internal use only) */ |
26 | #define CRUSH_ITEM_NONE 0x7fffffff /* no result */ | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * CRUSH uses user-defined "rules" to describe how inputs should be | 29 | * CRUSH uses user-defined "rules" to describe how inputs should be |
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index a8605245d190..caeb1066bea3 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c | |||
@@ -474,6 +474,148 @@ reject: | |||
474 | 474 | ||
475 | 475 | ||
476 | /** | 476 | /** |
477 | * choose indep: alternative breadth-first positionally stable mapping | ||
478 | * | ||
479 | */ | ||
480 | static void crush_choose_indep(const struct crush_map *map, | ||
481 | struct crush_bucket *bucket, | ||
482 | const __u32 *weight, int weight_max, | ||
483 | int x, int numrep, int type, | ||
484 | int *out, int outpos, | ||
485 | int recurse_to_leaf, | ||
486 | int *out2) | ||
487 | { | ||
488 | struct crush_bucket *in = bucket; | ||
489 | int left = numrep - outpos; | ||
490 | int rep; | ||
491 | unsigned int ftotal; | ||
492 | int r; | ||
493 | int i; | ||
494 | int item = 0; | ||
495 | int itemtype; | ||
496 | int collide; | ||
497 | |||
498 | dprintk("CHOOSE%s INDEP bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", | ||
499 | bucket->id, x, outpos, numrep); | ||
500 | |||
501 | /* initially my result is undefined */ | ||
502 | for (rep = outpos; rep < numrep; rep++) { | ||
503 | out[rep] = CRUSH_ITEM_UNDEF; | ||
504 | if (out2) | ||
505 | out2[rep] = CRUSH_ITEM_UNDEF; | ||
506 | } | ||
507 | |||
508 | for (ftotal = 0; left > 0 && ftotal < map->choose_total_tries; ftotal++) { | ||
509 | for (rep = outpos; rep < numrep; rep++) { | ||
510 | if (out[rep] != CRUSH_ITEM_UNDEF) | ||
511 | continue; | ||
512 | |||
513 | in = bucket; /* initial bucket */ | ||
514 | |||
515 | /* choose through intervening buckets */ | ||
516 | for (;;) { | ||
517 | r = rep; | ||
518 | |||
519 | /* be careful */ | ||
520 | if (in->alg == CRUSH_BUCKET_UNIFORM && | ||
521 | in->size % numrep == 0) | ||
522 | /* r'=r+(n+1)*f_total */ | ||
523 | r += (numrep+1) * ftotal; | ||
524 | else | ||
525 | /* r' = r + n*f_total */ | ||
526 | r += numrep * ftotal; | ||
527 | |||
528 | /* bucket choose */ | ||
529 | if (in->size == 0) { | ||
530 | dprintk(" empty bucket\n"); | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | item = crush_bucket_choose(in, x, r); | ||
535 | if (item >= map->max_devices) { | ||
536 | dprintk(" bad item %d\n", item); | ||
537 | out[rep] = CRUSH_ITEM_NONE; | ||
538 | if (out2) | ||
539 | out2[rep] = CRUSH_ITEM_NONE; | ||
540 | left--; | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | /* desired type? */ | ||
545 | if (item < 0) | ||
546 | itemtype = map->buckets[-1-item]->type; | ||
547 | else | ||
548 | itemtype = 0; | ||
549 | dprintk(" item %d type %d\n", item, itemtype); | ||
550 | |||
551 | /* keep going? */ | ||
552 | if (itemtype != type) { | ||
553 | if (item >= 0 || | ||
554 | (-1-item) >= map->max_buckets) { | ||
555 | dprintk(" bad item type %d\n", type); | ||
556 | out[rep] = CRUSH_ITEM_NONE; | ||
557 | if (out2) | ||
558 | out2[rep] = | ||
559 | CRUSH_ITEM_NONE; | ||
560 | left--; | ||
561 | break; | ||
562 | } | ||
563 | in = map->buckets[-1-item]; | ||
564 | continue; | ||
565 | } | ||
566 | |||
567 | /* collision? */ | ||
568 | collide = 0; | ||
569 | for (i = outpos; i < numrep; i++) { | ||
570 | if (out[i] == item) { | ||
571 | collide = 1; | ||
572 | break; | ||
573 | } | ||
574 | } | ||
575 | if (collide) | ||
576 | break; | ||
577 | |||
578 | if (recurse_to_leaf) { | ||
579 | if (item < 0) { | ||
580 | crush_choose_indep(map, | ||
581 | map->buckets[-1-item], | ||
582 | weight, weight_max, | ||
583 | x, rep+1, 0, | ||
584 | out2, rep, | ||
585 | 0, NULL); | ||
586 | if (out2[rep] == CRUSH_ITEM_NONE) { | ||
587 | /* placed nothing; no leaf */ | ||
588 | break; | ||
589 | } | ||
590 | } else { | ||
591 | /* we already have a leaf! */ | ||
592 | out2[rep] = item; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | /* out? */ | ||
597 | if (itemtype == 0 && | ||
598 | is_out(map, weight, weight_max, item, x)) | ||
599 | break; | ||
600 | |||
601 | /* yay! */ | ||
602 | out[rep] = item; | ||
603 | left--; | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | } | ||
608 | for (rep = outpos; rep < numrep; rep++) { | ||
609 | if (out[rep] == CRUSH_ITEM_UNDEF) { | ||
610 | out[rep] = CRUSH_ITEM_NONE; | ||
611 | } | ||
612 | if (out2 && out2[rep] == CRUSH_ITEM_UNDEF) { | ||
613 | out2[rep] = CRUSH_ITEM_NONE; | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | |||
618 | /** | ||
477 | * crush_do_rule - calculate a mapping with the given input and rule | 619 | * crush_do_rule - calculate a mapping with the given input and rule |
478 | * @map: the crush_map | 620 | * @map: the crush_map |
479 | * @ruleno: the rule id | 621 | * @ruleno: the rule id |
@@ -556,15 +698,27 @@ int crush_do_rule(const struct crush_map *map, | |||
556 | continue; | 698 | continue; |
557 | } | 699 | } |
558 | j = 0; | 700 | j = 0; |
559 | osize += crush_choose(map, | 701 | if (firstn) { |
560 | map->buckets[-1-w[i]], | 702 | osize += crush_choose(map, |
561 | weight, weight_max, | 703 | map->buckets[-1-w[i]], |
562 | x, numrep, | 704 | weight, weight_max, |
563 | curstep->arg2, | 705 | x, numrep, |
564 | o+osize, j, | 706 | curstep->arg2, |
565 | firstn, | 707 | o+osize, j, |
566 | recurse_to_leaf, | 708 | firstn, |
567 | descend_once, c+osize); | 709 | recurse_to_leaf, |
710 | descend_once, c+osize); | ||
711 | } else { | ||
712 | crush_choose_indep(map, | ||
713 | map->buckets[-1-w[i]], | ||
714 | weight, weight_max, | ||
715 | x, numrep, | ||
716 | curstep->arg2, | ||
717 | o+osize, j, | ||
718 | recurse_to_leaf, | ||
719 | c+osize); | ||
720 | osize += numrep; | ||
721 | } | ||
568 | } | 722 | } |
569 | 723 | ||
570 | if (recurse_to_leaf) | 724 | if (recurse_to_leaf) |