return false;
if (choose_args.size() > 1)
return true;
+ if (choose_args.begin()->first != DEFAULT_CHOOSE_ARGS)
+ return true;
crush_choose_arg_map arg_map = choose_args.begin()->second;
for (__u32 i = 0; i < arg_map.size; i++) {
crush_choose_arg *arg = &arg_map.args[i];
::encode(class_name, bl);
::encode(class_bucket, bl);
+ // choose args
__u32 size = (__u32)choose_args.size();
::encode(size, bl);
for (auto c : choose_args) {
using namespace std;
class CrushWrapper {
public:
+ // magic value used by OSDMap for a "default" fallback choose_args, used if
+ // the choose_arg_map passed to do_rule does not exist. if this also
+ // doesn't exist, fall back to canonical weights.
+ enum {
+ DEFAULT_CHOOSE_ARGS = -1
+ };
+
std::map<int32_t, string> type_map; /* bucket/device type names */
std::map<int32_t, string> name_map; /* bucket/device names */
std::map<int32_t, string> rule_name_map;
std::map<int32_t, string> class_name; /* class id -> class name */
std::map<string, int32_t> class_rname; /* class name -> class id */
std::map<int32_t, map<int32_t, int32_t> > class_bucket; /* bucket[id][class] == id */
- std::map<uint64_t, crush_choose_arg_map> choose_args;
+ std::map<int64_t, crush_choose_arg_map> choose_args;
private:
struct crush_map *crush;
return choose_args.count(choose_args_index);
}
+ crush_choose_arg_map choose_args_get_with_fallback(
+ uint64_t choose_args_index) const {
+ auto i = choose_args.find(choose_args_index);
+ if (i == choose_args.end()) {
+ i = choose_args.find(DEFAULT_CHOOSE_ARGS);
+ }
+ if (i == choose_args.end()) {
+ crush_choose_arg_map arg_map;
+ arg_map.args = NULL;
+ arg_map.size = 0;
+ return arg_map;
+ } else {
+ return i->second;
+ }
+ }
crush_choose_arg_map choose_args_get(uint64_t choose_args_index) const {
auto i = choose_args.find(choose_args_index);
if (i == choose_args.end()) {
int rawout[maxout];
char work[crush_work_size(crush, maxout)];
crush_init_workspace(crush, work);
- crush_choose_arg_map arg_map = choose_args_get(choose_args_index);
+ crush_choose_arg_map arg_map = choose_args_get_with_fallback(
+ choose_args_index);
int numrep = crush_do_rule(crush, rule, x, rawout, maxout, &weight[0],
weight.size(), work, arg_map.args);
if (numrep < 0)
arg_map.args = choose_args;
uint64_t features = CEPH_FEATURE_CRUSH_TUNABLES5|CEPH_FEATURE_INCARNATION_2;
+ int64_t caid = CrushWrapper::DEFAULT_CHOOSE_ARGS;
// if the client is capable, encode choose_args
{
- c.choose_args[0] = arg_map;
+ c.choose_args[caid] = arg_map;
bufferlist bl;
c.encode(bl, features|CEPH_FEATURE_CRUSH_CHOOSE_ARGS);
bufferlist::iterator i(bl.begin());
CrushWrapper c_new;
c_new.decode(i);
ASSERT_EQ(1u, c_new.choose_args.size());
- ASSERT_EQ(1u, c_new.choose_args[0].args[-1-id].weight_set_size);
- ASSERT_EQ(weights, c_new.choose_args[0].args[-1-id].weight_set[0].weights[0]);
+ ASSERT_EQ(1u, c_new.choose_args[caid].args[-1-id].weight_set_size);
+ ASSERT_EQ(weights, c_new.choose_args[caid].args[-1-id].weight_set[0].weights[0]);
ASSERT_EQ(weight, c_new.get_bucket_item_weightf(id, 0));
}
// if the client is not compatible, copy choose_arg in the weights
{
- c.choose_args[0] = arg_map;
+ c.choose_args[caid] = arg_map;
bufferlist bl;
c.encode(bl, features);
c.choose_args.clear();