#ifdef __KERNEL__ # include <linux/string.h> # include <linux/slab.h> # include <linux/bug.h> # include <linux/kernel.h> # include <linux/crush/crush.h> # include <linux/crush/hash.h> # include <linux/crush/mapper.h> #else # include "crush_compat.h" # include "crush.h" # include "hash.h" # include "mapper.h" #endif #include"crush_ln_table.h"
#define dprintk(args...) /* printf(args) */
/* *ImplementthecoreCRUSHmappingalgorithm.
*/
/** *crush_find_rule-findacrush_ruleidforagivenruleset,type,andsize. *@map:thecrush_map *@ruleset:thestoragerulesetid(userdefined) *@type:storagerulesettype(userdefined) *@size:outputsetsize
*/ int crush_find_rule(conststruct crush_map *map, int ruleset, int type, int size)
{
__u32 i;
for (i = 0; i < map->max_rules; i++) { if (map->rules[i] &&
map->rules[i]->mask.ruleset == ruleset &&
map->rules[i]->mask.type == type &&
map->rules[i]->mask.min_size <= size &&
map->rules[i]->mask.max_size >= size) return i;
} return -1;
}
/* *Choosebasedonarandompermutationofthebucket. * *Weusedtousesomeprimenumberarithmetictodothis,butit *wasn'tveryrandom,andhadsomeotherbadbehaviors.Instead,we *calculateanactualrandompermutationofthebucketmembers. *Sincethisisexpensive,weoptimizeforther=0case,which *capturesthevastmajorityofcalls.
*/ staticint bucket_perm_choose(conststruct crush_bucket *bucket, struct crush_work_bucket *work, int x, int r)
{ unsignedint pr = r % bucket->size; unsignedint i, s;
/* start a new permutation if @x has changed */ if (work->perm_x != (__u32)x || work->perm_n == 0) {
dprintk("bucket %d new x=%d\n", bucket->id, x);
work->perm_x = x;
/* optimize common r=0 case */ if (pr == 0) {
s = crush_hash32_3(bucket->hash, x, bucket->id, 0) %
bucket->size;
work->perm[0] = s;
work->perm_n = 0xffff; /* magic value, see below */ goto out;
}
for (i = 0; i < bucket->size; i++)
work->perm[i] = i;
work->perm_n = 0;
} elseif (work->perm_n == 0xffff) { /* clean up after the r=0 case above */ for (i = 1; i < bucket->size; i++)
work->perm[i] = i;
work->perm[work->perm[0]] = 0;
work->perm_n = 1;
}
/* calculate permutation up to pr */ for (i = 0; i < work->perm_n; i++)
dprintk(" perm_choose have %d: %d\n", i, work->perm[i]); while (work->perm_n <= pr) { unsignedint p = work->perm_n; /* no point in swapping the final entry */ if (p < bucket->size - 1) {
i = crush_hash32_3(bucket->hash, x, bucket->id, p) %
(bucket->size - p); if (i) { unsignedint t = work->perm[p + i];
work->perm[p + i] = work->perm[p];
work->perm[p] = t;
}
dprintk(" perm_choose swap %d with %d\n", p, p+i);
}
work->perm_n++;
} for (i = 0; i < bucket->size; i++)
dprintk(" perm_choose %d: %d\n", i, work->perm[i]);
/* list */ staticint bucket_list_choose(conststruct crush_bucket_list *bucket, int x, int r)
{ int i;
for (i = bucket->h.size-1; i >= 0; i--) {
__u64 w = crush_hash32_4(bucket->h.hash, x, bucket->h.items[i],
r, bucket->h.id);
w &= 0xffff;
dprintk("list_choose i=%d x=%d r=%d item %d weight %x " "sw %x rand %llx",
i, x, r, bucket->h.items[i], bucket->item_weights[i],
bucket->sum_weights[i], w);
w *= bucket->sum_weights[i];
w = w >> 16; /*dprintk(" scaled %llx\n", w);*/ if (w < bucket->item_weights[i]) { return bucket->h.items[i];
}
}
dprintk("bad list sums for bucket %d\n", bucket->h.id); return bucket->h.items[0];
}
/* (binary) tree */ staticint height(int n)
{ int h = 0; while ((n & 1) == 0) {
h++;
n = n >> 1;
} return h;
}
staticint left(int x)
{ int h = height(x); return x - (1 << (h-1));
}
staticint right(int x)
{ int h = height(x); return x + (1 << (h-1));
}
staticint terminal(int x)
{ return x & 1;
}
staticint bucket_tree_choose(conststruct crush_bucket_tree *bucket, int x, int r)
{ int n;
__u32 w;
__u64 t;
/* start at root */
n = bucket->num_nodes >> 1;
while (!terminal(n)) { int l; /* pick point in [0, w) */
w = bucket->node_weights[n];
t = (__u64)crush_hash32_4(bucket->h.hash, x, n, r,
bucket->h.id) * (__u64)w;
t = t >> 32;
/* descend to the left or right? */
l = left(n); if (t < bucket->node_weights[l])
n = l; else
n = right(n);
}
return bucket->h.items[n >> 1];
}
/* straw */
staticint bucket_straw_choose(conststruct crush_bucket_straw *bucket, int x, int r)
{
__u32 i; int high = 0;
__u64 high_draw = 0;
__u64 draw;
for (i = 0; i < bucket->h.size; i++) {
draw = crush_hash32_3(bucket->h.hash, x, bucket->h.items[i], r);
draw &= 0xffff;
draw *= bucket->straws[i]; if (i == 0 || draw > high_draw) {
high = i;
high_draw = draw;
}
} return bucket->h.items[high];
}
staticint bucket_straw2_choose(conststruct crush_bucket_straw2 *bucket, int x, int r, conststruct crush_choose_arg *arg, int position)
{ unsignedint i, high = 0; unsignedint u;
__s64 ln, draw, high_draw = 0;
__u32 *weights = get_choose_arg_weights(bucket, arg, position);
__s32 *ids = get_choose_arg_ids(bucket, arg);
for (i = 0; i < bucket->h.size; i++) {
dprintk("weight 0x%x item %d\n", weights[i], ids[i]); if (weights[i]) {
u = crush_hash32_3(bucket->h.hash, x, ids[i], r);
u &= 0xffff;
/* *crush_choose_indep:alternativebreadth-firstpositionallystablemapping
*/ staticvoid crush_choose_indep(conststruct crush_map *map, struct crush_work *work, conststruct crush_bucket *bucket, const __u32 *weight, int weight_max, int x, int left, int numrep, int type, int *out, int outpos, unsignedint tries, unsignedint recurse_tries, int recurse_to_leaf, int *out2, int parent_r, conststruct crush_choose_arg *choose_args)
{ conststruct crush_bucket *in = bucket; int endpos = outpos + left; int rep; unsignedint ftotal; int r; int i; int item = 0; int itemtype; int collide;
/* initially my result is undefined */ for (rep = outpos; rep < endpos; rep++) {
out[rep] = CRUSH_ITEM_UNDEF; if (out2)
out2[rep] = CRUSH_ITEM_UNDEF;
}
/* choose through intervening buckets */ for (;;) { /* note: we base the choice on the position *eveninthenestedcall.thatmeansthat *ifthefirstlayerchoosesthesamebucket *inadifferentposition,wewilltendto *chooseadifferentiteminthatbucket. *thiswillinvolvemoredevicesindata *movementandtendtodistributetheload.
*/
r = rep + parent_r;
/* be careful */ if (in->alg == CRUSH_BUCKET_UNIFORM &&
in->size % numrep == 0) /* r'=r+(n+1)*f_total */
r += (numrep+1) * ftotal; else /* r' = r + n*f_total */
r += numrep * ftotal;
/** *crush_do_rule-calculateamappingwiththegiveninputandrule *@map:thecrush_map *@ruleno:theruleid *@x:hashinput *@result:pointertoresultvector *@result_max:maximumresultsize *@weight:weightvector(formapleaves) *@weight_max:sizeofweightvector *@cwin:pointertoatleastcrush_work_size()bytesofmemory *@choose_args:weightsandidsforeachknownbucket
*/ int crush_do_rule(conststruct crush_map *map, int ruleno, int x, int *result, int result_max, const __u32 *weight, int weight_max, void *cwin, conststruct crush_choose_arg *choose_args)
{ int result_len; struct crush_work *cw = cwin; int *a = cwin + map->working_size; int *b = a + result_max; int *c = b + result_max; int *w = a; int *o = b; int recurse_to_leaf; int wsize = 0; int osize; conststruct crush_rule *rule;
__u32 step; int i, j; int numrep; int out_size; /* *theoriginalchoose_total_triesvaluewasoffbyone(it *counted"retries"andnot"tries").addone.
*/ int choose_tries = map->choose_total_tries + 1; int choose_leaf_tries = 0; /* *thelocaltriesvalueswerecountedas"retries",though, *andneednoadjustment
*/ int choose_local_retries = map->choose_local_tries; int choose_local_fallback_retries = map->choose_local_fallback_tries;
int vary_r = map->chooseleaf_vary_r; int stable = map->chooseleaf_stable;
if ((__u32)ruleno >= map->max_rules) {
dprintk(" bad ruleno %d\n", ruleno); return0;
}
rule = map->rules[ruleno];
result_len = 0;
for (step = 0; step < rule->len; step++) { int firstn = 0; conststruct crush_rule_step *curstep = &rule->steps[step];
switch (curstep->op) { case CRUSH_RULE_TAKE: if ((curstep->arg1 >= 0 &&
curstep->arg1 < map->max_devices) ||
(-1-curstep->arg1 >= 0 &&
-1-curstep->arg1 < map->max_buckets &&
map->buckets[-1-curstep->arg1])) {
w[0] = curstep->arg1;
wsize = 1;
} else {
dprintk(" bad take value %d\n", curstep->arg1);
} break;
case CRUSH_RULE_SET_CHOOSE_TRIES: if (curstep->arg1 > 0)
choose_tries = curstep->arg1; break;
case CRUSH_RULE_SET_CHOOSELEAF_TRIES: if (curstep->arg1 > 0)
choose_leaf_tries = curstep->arg1; break;
case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES: if (curstep->arg1 >= 0)
choose_local_retries = curstep->arg1; break;
case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES: if (curstep->arg1 >= 0)
choose_local_fallback_retries = curstep->arg1; break;
case CRUSH_RULE_SET_CHOOSELEAF_VARY_R: if (curstep->arg1 >= 0)
vary_r = curstep->arg1; break;
case CRUSH_RULE_SET_CHOOSELEAF_STABLE: if (curstep->arg1 >= 0)
stable = curstep->arg1; break;
case CRUSH_RULE_CHOOSELEAF_FIRSTN: case CRUSH_RULE_CHOOSE_FIRSTN:
firstn = 1;
fallthrough; case CRUSH_RULE_CHOOSELEAF_INDEP: case CRUSH_RULE_CHOOSE_INDEP: if (wsize == 0) break;
for (i = 0; i < wsize; i++) { int bno;
numrep = curstep->arg1; if (numrep <= 0) {
numrep += result_max; if (numrep <= 0) continue;
}
j = 0; /* make sure bucket id is valid */
bno = -1 - w[i]; if (bno < 0 || bno >= map->max_buckets) { /* w[i] is probably CRUSH_ITEM_NONE */
dprintk(" bad w[i] %d\n", w[i]); continue;
} if (firstn) { int recurse_tries; if (choose_leaf_tries)
recurse_tries =
choose_leaf_tries; elseif (map->chooseleaf_descend_once)
recurse_tries = 1; else
recurse_tries = choose_tries;
osize += crush_choose_firstn(
map,
cw,
map->buckets[bno],
weight, weight_max,
x, numrep,
curstep->arg2,
o+osize, j,
result_max-osize,
choose_tries,
recurse_tries,
choose_local_retries,
choose_local_fallback_retries,
recurse_to_leaf,
vary_r,
stable,
c+osize, 0,
choose_args);
} else {
out_size = ((numrep < (result_max-osize)) ?
numrep : (result_max-osize));
crush_choose_indep(
map,
cw,
map->buckets[bno],
weight, weight_max,
x, out_size, numrep,
curstep->arg2,
o+osize, j,
choose_tries,
choose_leaf_tries ?
choose_leaf_tries : 1,
recurse_to_leaf,
c+osize, 0,
choose_args);
osize += out_size;
}
}
if (recurse_to_leaf) /* copy final _leaf_ values to output set */
memcpy(o, c, osize*sizeof(*o));
/* swap o and w arrays */
swap(o, w);
wsize = osize; break;
case CRUSH_RULE_EMIT: for (i = 0; i < wsize && result_len < result_max; i++) {
result[result_len] = w[i];
result_len++;
}
wsize = 0; break;
default:
dprintk(" unknown op %d at step %d\n",
curstep->op, step); break;
}
}
return result_len;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.21Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.