Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / crush / builder.h
1 #ifndef CEPH_CRUSH_BUILDER_H
2 #define CEPH_CRUSH_BUILDER_H
3
4 #include "include/int_types.h"
5
6 struct crush_bucket;
7 struct crush_choose_arg;
8 struct crush_map;
9 struct crush_rule;
10
11 /** @ingroup API
12  *
13  * Allocate a crush_map with __malloc(3)__ and initialize it. The
14  * caller is responsible for deallocating the crush_map with
15  * crush_destroy().
16  *
17  * The content of the allocated crush_map is set with
18  * set_optimal_crush_map(). The caller is responsible for setting each
19  * tunable in the __crush_map__ for backward compatibility or mapping
20  * stability.
21  *
22  * @returns a pointer to the newly created crush_map or NULL
23  */
24 extern struct crush_map *crush_create();
25 /** @ingroup API
26  *
27  * Analyze the content of __map__ and set the internal values required
28  * before it can be used to map values with crush_do_rule(). The caller
29  * must make sure it is run before crush_do_rule() and after any
30  * function that modifies the __map__ (crush_add_bucket(), etc.).
31  *
32  * @param map the crush_map
33  */
34 extern void crush_finalize(struct crush_map *map);
35
36 /* rules */
37 /** @ingroup API
38  *
39  * Allocate an empty crush_rule structure large enough to store __len__ steps.
40  * Steps can be added to a rule via crush_rule_set_step(). The __ruleset__
41  * is a user defined integer, not used by __libcrush__ and stored in
42  * the allocated rule at __rule->mask.ruleset__.
43  *
44  * The rule is designed to allow crush_do_rule() to get at least __minsize__ items
45  * and at most __maxsize__ items.
46  *
47  * The __type__ is defined by the caller and will be used by
48  * crush_find_rule() when looking for a rule and by
49  * __CRUSH_RULE_CHOOSE*__ steps when looking for items.
50  *
51  * The caller is responsible for deallocating the returned pointer via
52  * crush_destroy_rule().
53  *
54  * If __malloc(3)__ fails, return NULL.
55  *
56  * @param len number of steps in the rule
57  * @param ruleset user defined value
58  * @param type user defined value
59  * @param minsize minimum number of items the rule can map
60  * @param maxsize maximum number of items the rule can map
61  *
62  * @returns a pointer to the newly created rule or NULL
63  */
64 extern struct crush_rule *crush_make_rule(int len, int ruleset, int type, int minsize, int maxsize);
65 /** @ingroup API
66  *
67  * Set the __pos__ step of the __rule__ to an operand and up to two arguments.
68  * The value of the operand __op__ determines if the arguments are used and how:
69  *
70  * - __CRUSH_RULE_NOOP__ do nothing.
71  * - __CRUSH_RULE_TAKE__ select the __arg1__ item
72  * - __CRUSH_RULE_EMIT__ append the selection to the results and clear
73  *     the selection
74  *
75  * - __CRUSH_RULE_CHOOSE_FIRSTN__ and __CRUSH_RULE_CHOOSE_INDEP__
76  *     recursively explore each bucket currently selected, looking for
77  *     __arg1__ items of type __arg2__ and select them.
78  * - __CRUSH_RULE_CHOOSELEAF_FIRSTN__ and __CRUSH_RULE_CHOOSELEAF_INDEP__
79  *     recursively explore each bucket currently selected, looking for
80  *     __arg1__ leaves within all the buckets of type __arg2__ and
81  *     select them.
82  *
83  * In all __CHOOSE__ steps, if __arg1__ is less than or equal to zero,
84  * the number of items to select is equal to the __max_result__ argument
85  * of crush_do_rule() minus __arg1__. It is common to set __arg1__ to zero
86  * to select as many items as requested by __max_result__.
87  *
88  * - __CRUSH_RULE_SET_CHOOSE_TRIES__ and __CRUSH_RULE_SET_CHOOSELEAF_TRIES__
89  *
90  *   The CHOOSE_FIRSTN and CHOOSE_INDEP rule step look for buckets of
91  *   a given type, randomly selecting them. If they are unlucky and
92  *   find the same bucket twice, they will try N+1 times (N being the
93  *   value of the choose_total_tries tunable). If there is a previous
94  *   SET_CHOOSE_TRIES step in the same rule, it will try C times
95  *   instead (C being the value of the argument of the
96  *   SET_CHOOSE_TRIES step).
97  *
98  *   Note: the __choose_total_tries__ tunable defined in crush_map is
99  *   the number of retry, not the number of tries. The number of tries
100  *   is the number of retry+1. The SET_CHOOSE_TRIES rule step sets the
101  *   number of tries and does not need the + 1. This confusing
102  *   difference is inherited from an off-by-one bug from years ago.
103  *
104  *   The CHOOSELEAF_FIRSTN and CHOOSELEAF_INDEP rule step do the same
105  *   as CHOOSE_FIRSTN and CHOOSE_INDEP but also recursively explore
106  *   each bucket found, looking for a single device. The same device
107  *   may be found in two different buckets because the crush map is
108  *   not a strict hierarchy, it is a DAG. When such a collision
109  *   happens, they will try again. The number of times they try to
110  *   find a non colliding device is:
111  *
112  *   - If FIRSTN and there is no previous SET_CHOOSELEAF_TRIES rule
113  *     step: try N + 1 times (N being the value of the
114  *     __choose_total_tries__ tunable defined in crush_map)
115  *
116  *   - If FIRSTN and there is a previous SET_CHOOSELEAF_TRIES rule
117  *     step: try P times (P being the value of the argument of the
118  *     SET_CHOOSELEAF_TRIES rule step)
119  *
120  *   - If INDEP and there is no previous SET_CHOOSELEAF_TRIES rule
121  *     step: try 1 time.
122  *
123  *   - If INDEP and there is a previous SET_CHOOSELEAF_TRIES rule step: try
124  *     P times (P being the value of the argument of the SET_CHOOSELEAF_TRIES
125  *     rule step)
126  *
127  * @param rule the rule in which the step is inserted
128  * @param pos the zero based step index
129  * @param op one of __CRUSH_RULE_NOOP__, __CRUSH_RULE_TAKE__, __CRUSH_RULE_CHOOSE_FIRSTN__, __CRUSH_RULE_CHOOSE_INDEP__, __CRUSH_RULE_CHOOSELEAF_FIRSTN__, __CRUSH_RULE_CHOOSELEAF_INDEP__, __CRUSH_RULE_SET_CHOOSE_TRIES__, __CRUSH_RULE_SET_CHOOSELEAF_TRIES__ or __CRUSH_RULE_EMIT__
130  * @param arg1 first argument for __op__
131  * @param arg2 second argument for __op__
132  */
133 extern void crush_rule_set_step(struct crush_rule *rule, int pos, int op, int arg1, int arg2);
134 /** @ingroup API
135  *
136  * Add the __rule__ into the crush __map__ and assign it the
137  * __ruleno__ unique identifier. If __ruleno__ is -1, the function will
138  * assign the lowest available identifier. The __ruleno__ value must be
139  * a positive integer lower than __CRUSH_MAX_RULES__.
140  *
141  * - return -ENOSPC if the rule identifier is >= __CRUSH_MAX_RULES__
142  * - return -ENOMEM if __realloc(3)__ fails to expand the array of
143  *   rules in the __map__
144  *
145  * @param map the crush_map
146  * @param rule the rule to add to the __map__
147  * @param ruleno a positive integer < __CRUSH_MAX_RULES__ or -1
148  *
149  * @returns the rule unique identifier on success, < 0 on error
150  */
151 extern int crush_add_rule(struct crush_map *map, struct crush_rule *rule, int ruleno);
152
153 /* buckets */
154 extern int crush_get_next_bucket_id(struct crush_map *map);
155 /** @ingroup API
156  *
157  * Add __bucket__ into the crush __map__ and assign it the
158  * __bucketno__ unique identifier. If __bucketno__ is 0, the function
159  * will assign the lowest available identifier.  The bucket identifier
160  * must be a negative integer. The bucket identifier is returned via
161  * __idout__.
162  *
163  * - return -ENOMEM if __realloc(3)__ fails to expand the array of
164  *   buckets in the __map__
165  * - return -EEXIST if the __bucketno__ identifier is already assigned
166  *   to another bucket.
167  *
168  * @param[in] map the crush_map
169  * @param[in] bucketno the bucket unique identifer or 0
170  * @param[in] bucket the bucket to add to the __map__
171  * @param[out] idout a pointer to the bucket identifier
172  *
173  * @returns 0 on success, < 0 on error
174  */
175 extern int crush_add_bucket(struct crush_map *map,
176                             int bucketno,
177                             struct crush_bucket *bucket, int *idout);
178 /** @ingroup API
179  *
180  * Allocate a crush_bucket with __malloc(3)__ and initialize it. The
181  * content of the bucket is filled with __size__ items from
182  * __items__. The item selection is set to use __alg__ which is one of
183  * ::CRUSH_BUCKET_UNIFORM , ::CRUSH_BUCKET_LIST or
184  * ::CRUSH_BUCKET_STRAW2. The initial __items__ are assigned a
185  * weight from the __weights__ array, depending on the value of
186  * __alg__. If __alg__ is ::CRUSH_BUCKET_UNIFORM, all items are set
187  * to have a weight equal to __weights[0]__, otherwise the weight of
188  * __items[x]__ is set to be the value of __weights[x]__.
189  *
190  * The caller is responsible for deallocating the returned pointer via
191  * crush_destroy_bucket().
192  *
193  * @param map __unused__
194  * @param alg algorithm for item selection
195  * @param hash always set to CRUSH_HASH_RJENKINS1
196  * @param type user defined bucket type
197  * @param size of the __items__ array
198  * @param items array of __size__ items
199  * @param weights the weight of each item in __items__, depending on __alg__
200  *
201  * @returns a pointer to the newly created bucket or NULL
202  */
203 struct crush_bucket *crush_make_bucket(struct crush_map *map, int alg, int hash, int type, int size, int *items, int *weights);
204 extern struct crush_choose_arg *crush_make_choose_args(struct crush_map *map, int num_positions);
205 extern void crush_destroy_choose_args(struct crush_choose_arg *args);
206 /** @ingroup API
207  *
208  * Add __item__ to __bucket__ with __weight__. The weight of the new
209  * item is added to the weight of the bucket so that it reflects
210  * the total weight of all items.
211  *
212  * If __bucket->alg__ is ::CRUSH_BUCKET_UNIFORM, the value of __weight__ must be equal to
213  * __(struct crush_bucket_uniform *)bucket->item_weight__.
214  *
215  * - return -ENOMEM if the __bucket__ cannot be resized with __realloc(3)__.
216  * - return -ERANGE if adding __weight__ to the weight of the bucket overflows.
217  * - return -EINVAL if __bucket->alg__ is ::CRUSH_BUCKET_UNIFORM and
218  *   the __weight__ is not equal to __(struct crush_bucket_uniform *)bucket->item_weight__.
219  * - return -1 if the value of __bucket->alg__ is unknown.
220  *
221  * @returns 0 on success, < 0 on error
222  */
223 extern int crush_bucket_add_item(struct crush_map *map, struct crush_bucket *bucket, int item, int weight);
224 /** @ingroup API
225  *
226  * If __bucket->alg__ is ::CRUSH_BUCKET_UNIFORM,
227  * __(struct crush_bucket_uniform *)bucket->item_weight__ is set to __weight__ and the
228  * weight of the bucket is set to be the number of items in the bucket times the weight.
229  * The return value is the difference between the new bucket weight and the former
230  * bucket weight. The __item__ argument is ignored.
231  *
232  * If __bucket->alg__ is different from ::CRUSH_BUCKET_UNIFORM,
233  * set the  __weight__ of  __item__ in __bucket__. The former weight of the
234  * item is subtracted from the weight of the bucket and the new weight is added.
235  * The return value is the difference between the new item weight and the former
236  * item weight.
237  *
238  * @returns the difference between the new weight and the former weight
239  */
240 extern int crush_bucket_adjust_item_weight(struct crush_map *map, struct crush_bucket *bucket, int item, int weight);
241 /** @ingroup API
242  *
243  * Recursively update the weight of __bucket__ and its children, deep
244  * first. The __bucket__ weight is set to the sum of the weight of the
245  * items it contains.
246  *
247  * - return -ERANGE if the sum of the weight of the items in __bucket__ overflows.
248  * - return -1 if the value of __bucket->alg__ is unknown.
249  *
250  * @param map a crush_map containing __bucket__
251  * @param bucket the root of the tree to reweight
252  * @returns 0 on success, < 0 on error
253  */
254 extern int crush_reweight_bucket(struct crush_map *map, struct crush_bucket *bucket);
255 /** @ingroup API
256  *
257  * Remove __bucket__ from __map__ and deallocate it via crush_destroy_bucket().
258  * __assert(3)__ that __bucket__ is in __map__. The caller is responsible for
259  * making sure the bucket is not the child of any other bucket in the __map__.
260  *
261  * @param map a crush_map containing __bucket__
262  * @param bucket the bucket to remove from __map__
263  * @returns 0
264  */
265 extern int crush_remove_bucket(struct crush_map *map, struct crush_bucket *bucket);
266 /** @ingroup API
267  *
268  * Remove __item__ from __bucket__ and subtract the item weight from
269  * the bucket weight. If the weight of the item is greater than the
270  * weight of the bucket, silentely set the bucket weight to zero.
271  *
272  * - return -ENOMEM if the __bucket__ cannot be sized down with __realloc(3)__.
273  * - return -1 if the value of __bucket->alg__ is unknown.
274  *
275  * @param map __unused__
276  * @param bucket the bucket from which __item__ is removed
277  * @param item the item to remove from __bucket__
278  * @returns 0 on success, < 0 on error
279  */
280 extern int crush_bucket_remove_item(struct crush_map *map, struct crush_bucket *bucket, int item);
281
282 struct crush_bucket_uniform *
283 crush_make_uniform_bucket(int hash, int type, int size,
284                           int *items,
285                           int item_weight);
286 struct crush_bucket_list*
287 crush_make_list_bucket(int hash, int type, int size,
288                        int *items,
289                        int *weights);
290 struct crush_bucket_tree*
291 crush_make_tree_bucket(int hash, int type, int size,
292                        int *items,    /* in leaf order */
293                        int *weights);
294 struct crush_bucket_straw *
295 crush_make_straw_bucket(struct crush_map *map,
296                         int hash, int type, int size,
297                         int *items,
298                         int *weights);
299
300 extern int crush_addition_is_unsafe(__u32 a, __u32 b);
301 extern int crush_multiplication_is_unsafe(__u32  a, __u32 b);
302
303 /** @ingroup API
304  *
305  * Set the __map__ tunables to implement the most ancient behavior,
306  * for backward compatibility purposes only.
307  *
308  * - choose_local_tries == 2
309  * - choose_local_fallback_tries == 5
310  * - choose_total_tries == 19
311  * - chooseleaf_descend_once == 0
312  * - chooseleaf_vary_r == 0
313  * - straw_calc_version == 0
314  * - chooseleaf_stable = 0
315  *
316  * See the __crush_map__ documentation for more information about
317  * each tunable.
318  *
319  * @param map a crush_map
320  */
321 extern void set_legacy_crush_map(struct crush_map *map);
322 /** @ingroup API
323  *
324  * Set the __map__ tunables to implement the optimal behavior. These
325  * are the values set by crush_create(). It does not guarantee a
326  * stable mapping after an upgrade.
327  *
328  * For instance when a bug is fixed it may significantly change the
329  * mapping. In that case a new tunable (say tunable_new) is added so
330  * the caller can control when the bug fix is activated. The
331  * set_optimal_crush_map() function will always set all tunables,
332  * including tunable_new, to fix all bugs even if it means changing
333  * the mapping. If the caller needs fine grained control on the
334  * tunables to upgrade to a new version without changing the mapping,
335  * it needs to set the __crush_map__ tunables individually.
336  *
337  * See the __crush_map__ documentation for more information about
338  * each tunable.
339  *
340  * @param map a crush_map
341  */
342 extern void set_optimal_crush_map(struct crush_map *map);
343
344 #endif