There are incorrect nodes' weight in tree bucket when construct tree
bucket. The tree bucket don't store item id in items array, so the tree
bucket will not work correctly. The patch fix above bugs and add a
simple test for tree bucket.
Signed-off-by: Rongze Zhu <zrzhit@gmail.com>
(cherry picked from commit
13425488882d360fa740613dfcfd0d098c1b7616)
static int calc_depth(int size)
{
+ if (size == 0) {
+ return 0;
+ }
+
int depth = 1;
int t = size - 1;
while (t) {
bucket->h.type = type;
bucket->h.size = size;
+ if (size == 0) {
+ bucket->h.items = NULL;
+ bucket->h.perm = NULL;
+ bucket->h.weight = 0;
+ bucket->node_weights = NULL;
+ bucket->num_nodes = 0;
+ /* printf("size 0 depth 0 nodes 0\n"); */
+ return bucket;
+ }
+
bucket->h.items = malloc(sizeof(__s32)*size);
if (!bucket->h.items)
goto err;
node = crush_calc_tree_node(newsize-1);
bucket->node_weights[node] = weight;
+ /* if the depth increase, we need to initialize the new root node's weight before add bucket item */
+ int root = bucket->num_nodes/2;
+ if (depth >= 2 && (node - 1) == root) {
+ /* if the new item is the first node in right sub tree, so
+ * the root node initial weight is left sub tree's weight
+ */
+ bucket->node_weights[root] = bucket->node_weights[root/2];
+ }
+
for (j=1; j<depth; j++) {
node = parent(node);
- if (!crush_addition_is_unsafe(bucket->node_weights[node], weight))
+ if (crush_addition_is_unsafe(bucket->node_weights[node], weight))
return -ERANGE;
bucket->node_weights[node] += weight;
if (crush_addition_is_unsafe(bucket->h.weight, weight))
return -ERANGE;
+ bucket->h.items[newsize-1] = item;
bucket->h.weight += weight;
bucket->h.size++;
--- /dev/null
+ $ crushtool -i "$TESTDIR/tree.template" --add-item 0 1.0 device0 --loc host host0 --loc cluster cluster0 -o one > /dev/null
+ $ crushtool -i one --add-item 1 1.0 device1 --loc host host0 --loc cluster cluster0 -o two > /dev/null
+ $ crushtool -i two --add-item 2 1.0 device2 --loc host host0 --loc cluster cluster0 -o tree > /dev/null
+ $ crushtool -i tree --add-item 3 1.0 device3 --loc host host0 --loc cluster cluster0 -o four > /dev/null
+ $ crushtool -i four --add-item 4 1.0 device4 --loc host host0 --loc cluster cluster0 -o five > /dev/null
+ $ crushtool -i five --add-item 5 1.0 device5 --loc host host0 --loc cluster cluster0 -o six > /dev/null
+ $ crushtool -i six --add-item 6 1.0 device6 --loc host host0 --loc cluster cluster0 -o seven > /dev/null
+ $ crushtool -i seven --add-item 7 1.0 device7 --loc host host0 --loc cluster cluster0 -o eight > /dev/null
+ $ crushtool -d eight -o final
+ $ cmp final "$TESTDIR/tree.template.final"
--- /dev/null
+# begin crush map
+
+# devices
+device 0 device0
+device 1 device1
+device 2 device2
+device 3 device3
+device 4 device4
+device 5 device5
+device 6 device6
+device 7 device7
+
+# types
+type 0 device
+type 1 host
+type 2 cluster
+
+# buckets
+host host0 {
+ id -2 # do not change unnecessarily
+ # weight 8.000
+ alg tree # do not change pos for existing items unnecessarily
+ hash 0 # rjenkins1
+ item device0 weight 1.000 pos 0
+ item device1 weight 1.000 pos 1
+ item device2 weight 1.000 pos 2
+ item device3 weight 1.000 pos 3
+ item device4 weight 1.000 pos 4
+ item device5 weight 1.000 pos 5
+ item device6 weight 1.000 pos 6
+ item device7 weight 1.000 pos 7
+}
+cluster cluster0 {
+ id -1 # do not change unnecessarily
+ # weight 8.000
+ alg tree # do not change pos for existing items unnecessarily
+ hash 0 # rjenkins1
+ item host0 weight 8.000 pos 0
+}
+
+# rules
+rule data {
+ ruleset 0
+ type replicated
+ min_size 1
+ max_size 10
+ step take cluster0
+ step chooseleaf firstn 0 type host
+ step emit
+}
+rule metadata {
+ ruleset 1
+ type replicated
+ min_size 1
+ max_size 10
+ step take cluster0
+ step chooseleaf firstn 0 type host
+ step emit
+}
+rule rbd {
+ ruleset 2
+ type replicated
+ min_size 1
+ max_size 10
+ step take cluster0
+ step chooseleaf firstn 0 type host
+ step emit
+}
+
+# end crush map