aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/crush/crush.h3
-rw-r--r--net/ceph/crush/mapper.c172
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 */
480static 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)