/* SPDX-License-Identifier: GPL-2.0 */ #ifndef CEPH_CRUSH_CRUSH_H #define CEPH_CRUSH_CRUSH_H #ifdef __KERNEL__ # include <linux/rbtree.h> # include <linux/types.h> #else # include "crush_compat.h" #endif /* * CRUSH is a pseudo-random data distribution algorithm that * efficiently distributes input values (typically, data objects) * across a heterogeneous, structured storage cluster. * * The algorithm was originally described in detail in this paper * (although the algorithm has evolved somewhat since then): * * https://www.ssrc.ucsc.edu/Papers/weil-sc06.pdf * * LGPL2 */ #define CRUSH_MAGIC … #define CRUSH_MAX_DEPTH … #define CRUSH_MAX_RULESET … #define CRUSH_MAX_RULES … #define CRUSH_MAX_DEVICE_WEIGHT … #define CRUSH_MAX_BUCKET_WEIGHT … #define CRUSH_ITEM_UNDEF … #define CRUSH_ITEM_NONE … /* * CRUSH uses user-defined "rules" to describe how inputs should be * mapped to devices. A rule consists of sequence of steps to perform * to generate the set of output devices. */ struct crush_rule_step { … }; /* step op codes */ enum { … }; /* * for specifying choose num (arg1) relative to the max parameter * passed to do_rule */ #define CRUSH_CHOOSE_N … #define CRUSH_CHOOSE_N_MINUS(x) … /* * The rule mask is used to describe what the rule is intended for. * Given a ruleset and size of output set, we search through the * rule list for a matching rule_mask. */ struct crush_rule_mask { … }; struct crush_rule { … }; #define crush_rule_size(len) … /* * A bucket is a named container of other items (either devices or * other buckets). Items within a bucket are chosen using one of a * few different algorithms. The table summarizes how the speed of * each option measures up against mapping stability when items are * added or removed. * * Bucket Alg Speed Additions Removals * ------------------------------------------------ * uniform O(1) poor poor * list O(n) optimal poor * tree O(log n) good good * straw O(n) better better * straw2 O(n) optimal optimal */ enum { … }; extern const char *crush_bucket_alg_name(int alg); /* * although tree was a legacy algorithm, it has been buggy, so * exclude it. */ #define CRUSH_LEGACY_ALLOWED_BUCKET_ALGS … struct crush_bucket { … }; /** @ingroup API * * Replacement weights for each item in a bucket. The size of the * array must be exactly the size of the straw2 bucket, just as the * item_weights array. * */ struct crush_weight_set { … }; /** @ingroup API * * Replacement weights and ids for a given straw2 bucket, for * placement purposes. * * When crush_do_rule() chooses the Nth item from a straw2 bucket, the * replacement weights found at __weight_set[N]__ are used instead of * the weights from __item_weights__. If __N__ is greater than * __weight_set_size__, the weights found at __weight_set_size-1__ are * used instead. For instance if __weight_set__ is: * * [ [ 0x10000, 0x20000 ], // position 0 * [ 0x20000, 0x40000 ] ] // position 1 * * choosing the 0th item will use position 0 weights [ 0x10000, 0x20000 ] * choosing the 1th item will use position 1 weights [ 0x20000, 0x40000 ] * choosing the 2th item will use position 1 weights [ 0x20000, 0x40000 ] * etc. * */ struct crush_choose_arg { … }; /** @ingroup API * * Replacement weights and ids for each bucket in the crushmap. The * __size__ of the __args__ array must be exactly the same as the * __map->max_buckets__. * * The __crush_choose_arg__ at index N will be used when choosing * an item from the bucket __map->buckets[N]__ bucket, provided it * is a straw2 bucket. * */ struct crush_choose_arg_map { … }; struct crush_bucket_uniform { … }; struct crush_bucket_list { … }; struct crush_bucket_tree { … }; struct crush_bucket_straw { … }; struct crush_bucket_straw2 { … }; /* * CRUSH map includes all buckets, rules, etc. */ struct crush_map { … }; /* crush.c */ extern int crush_get_bucket_item_weight(const struct crush_bucket *b, int pos); extern void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b); extern void crush_destroy_bucket_list(struct crush_bucket_list *b); extern void crush_destroy_bucket_tree(struct crush_bucket_tree *b); extern void crush_destroy_bucket_straw(struct crush_bucket_straw *b); extern void crush_destroy_bucket_straw2(struct crush_bucket_straw2 *b); extern void crush_destroy_bucket(struct crush_bucket *b); extern void crush_destroy_rule(struct crush_rule *r); extern void crush_destroy(struct crush_map *map); static inline int crush_calc_tree_node(int i) { … } /* * These data structures are private to the CRUSH implementation. They * are exposed in this header file because builder needs their * definitions to calculate the total working size. * * Moving this out of the crush map allow us to treat the CRUSH map as * immutable within the mapper and removes the requirement for a CRUSH * map lock. */ struct crush_work_bucket { … }; struct crush_work { … }; #ifdef __KERNEL__ /* osdmap.c */ void clear_crush_names(struct rb_root *root); void clear_choose_args(struct crush_map *c); #endif #endif