From: Loic Dachary Date: Fri, 26 May 2017 13:38:24 +0000 (+0300) Subject: crush: update choose_args when items are added/removed X-Git-Tag: ses5-milestone6~9^2~42^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b02ad2326de9823674ec01f11ed5d9a27cd40f89;p=ceph.git crush: update choose_args when items are added/removed When items are added: - the value in the weight set is set to the target weight. It is assumed that weight set are updated on a regular basis and will eventually be set to a value that prevents excessive over/under filling. - the value in the id list is set to the item id. When items are removed, their weight / ids in all choose_args are removed. Signed-off-by: Loic Dachary --- diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 848bd5609d1d..1a62590430c6 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -1347,11 +1347,54 @@ int CrushWrapper::remove_rule(int ruleno) int CrushWrapper::bucket_add_item(crush_bucket *bucket, int item, int weight) { + __u32 new_size = bucket->size + 1; + for (auto w : choose_args) { + crush_choose_arg_map arg_map = w.second; + crush_choose_arg *arg = &arg_map.args[-1-bucket->id]; + for (__u32 j = 0; j < arg->weight_set_size; j++) { + crush_weight_set *weight_set = &arg->weight_set[j]; + weight_set->weights = (__u32*)realloc(weight_set->weights, new_size * sizeof(__u32)); + assert(weight_set->size + 1 == new_size); + weight_set->weights[weight_set->size] = weight; + weight_set->size = new_size; + } + if (arg->ids_size) { + arg->ids = (int*)realloc(arg->ids, new_size * sizeof(int)); + assert(arg->ids_size + 1 == new_size); + arg->ids[arg->ids_size] = item; + arg->ids_size = new_size; + } + } return crush_bucket_add_item(crush, bucket, item, weight); } int CrushWrapper::bucket_remove_item(crush_bucket *bucket, int item) { + __u32 new_size = bucket->size - 1; + unsigned position; + for (position = 0; position < bucket->size; position++) + if (bucket->items[position] == item) + break; + assert(position != bucket->size); + for (auto w : choose_args) { + crush_choose_arg_map arg_map = w.second; + crush_choose_arg *arg = &arg_map.args[-1-bucket->id]; + for (__u32 j = 0; j < arg->weight_set_size; j++) { + crush_weight_set *weight_set = &arg->weight_set[j]; + assert(weight_set->size - 1 == new_size); + for (__u32 k = position; k < new_size; k++) + weight_set->weights[k] = weight_set->weights[k+1]; + weight_set->weights = (__u32*)realloc(weight_set->weights, new_size * sizeof(__u32)); + weight_set->size = new_size; + } + if (arg->ids_size) { + assert(arg->ids_size - 1 == new_size); + for (__u32 k = position; k < new_size; k++) + arg->ids[k] = arg->ids[k+1]; + arg->ids = (int*)realloc(arg->ids, new_size * sizeof(int)); + arg->ids_size = new_size; + } + } return crush_bucket_remove_item(crush, bucket, item); } diff --git a/src/test/crush/CMakeLists.txt b/src/test/crush/CMakeLists.txt index 0c7d7dca4d6b..81f587fec262 100644 --- a/src/test/crush/CMakeLists.txt +++ b/src/test/crush/CMakeLists.txt @@ -14,3 +14,4 @@ target_link_libraries(unittest_crush global m ${BLKID_LIBRARIES}) add_ceph_test(crush_weights.sh ${CMAKE_CURRENT_SOURCE_DIR}/crush_weights.sh) add_ceph_test(crush-classes.sh ${CMAKE_CURRENT_SOURCE_DIR}/crush-classes.sh) +add_ceph_test(crush-choose-args.sh ${CMAKE_CURRENT_SOURCE_DIR}/crush-choose-args.sh) diff --git a/src/test/crush/crush-choose-args-expected-one-more.txt b/src/test/crush/crush-choose-args-expected-one-more.txt new file mode 100644 index 000000000000..daff5611185d --- /dev/null +++ b/src/test/crush/crush-choose-args-expected-one-more.txt @@ -0,0 +1,67 @@ +# begin crush map +tunable choose_local_tries 0 +tunable choose_local_fallback_tries 0 +tunable choose_total_tries 50 +tunable chooseleaf_descend_once 1 +tunable chooseleaf_vary_r 1 +tunable straw_calc_version 1 +tunable allowed_bucket_algs 54 + +# devices +device 0 osd.0 +device 1 osd.1 + +# types +type 0 osd +type 1 host +type 2 chassis +type 3 rack +type 4 row +type 5 pdu +type 6 pod +type 7 room +type 8 datacenter +type 9 region +type 10 root + +# buckets +host fold { + id -2 # do not change unnecessarily + # weight 0.356 + alg straw2 + hash 0 # rjenkins1 + item osd.0 weight 0.178 + item osd.1 weight 0.178 +} +root default { + id -1 # do not change unnecessarily + # weight 0.356 + alg straw2 + hash 0 # rjenkins1 + item fold weight 0.356 +} + +# rules +rule replicated_ruleset { + ruleset 0 + type replicated + min_size 1 + max_size 10 + step take default + step choose firstn 0 type osd + step emit +} + +# choose_args +choose_args 0 { + { + bucket_id -2 + weight_set [ + [ 1.000 0.000 ] + [ 1.000 0.000 ] + ] + ids [ -20 1 ] + } +} + +# end crush map diff --git a/src/test/crush/crush-choose-args.sh b/src/test/crush/crush-choose-args.sh new file mode 100755 index 000000000000..3ea22b15b2e0 --- /dev/null +++ b/src/test/crush/crush-choose-args.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Copyright (C) 2017 Red Hat +# +# Author: Loic Dachary +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library Public License for more details. +# + +source $(dirname $0)/../detect-build-env-vars.sh +source $CEPH_ROOT/qa/workunits/ceph-helpers.sh + +function run() { + local dir=$1 + shift + + export CEPH_MON="127.0.0.1:7131" # git grep '\<7131\>' : there must be only one + export CEPH_ARGS + CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none " + CEPH_ARGS+="--mon-host=$CEPH_MON " + + local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')} + for func in $funcs ; do + setup $dir || return 1 + $func $dir || return 1 + teardown $dir || return 1 + done +} + +function TEST_choose_args() { + local dir=$1 + + run_mon $dir a || return 1 + run_osd $dir 0 || return 1 + + ceph osd getcrushmap > $dir/map || return 1 + crushtool -d $dir/map -o $dir/map.txt || return 1 + cat $dir/map.txt + sed -i -e '/end crush map/d' $dir/map.txt + cat >> $dir/map.txt < $dir/map-one-more || return 1 + crushtool -d $dir/map-one-more -o $dir/map-one-more.txt || return 1 + cat $dir/map-one-more.txt + diff -u $dir/map-one-more.txt $CEPH_ROOT/src/test/crush/crush-choose-args-expected-one-more.txt || return 1 + + destroy_osd $dir 1 || return 1 + ceph osd getcrushmap > $dir/map-one-less || return 1 + crushtool -d $dir/map-one-less -o $dir/map-one-less.txt || return 1 + diff -u $dir/map-one-less.txt $dir/map.txt || return 1 +} + +main crush-choose-args "$@" + +# Local Variables: +# compile-command: "cd ../../../build ; ln -sf ../src/ceph-disk/ceph_disk/main.py bin/ceph-disk && make -j4 && ../src/test/crush/crush-choose-args.sh" +# End: