Implement CrushWrapper::ruleset_exists that iterates over the existing
rulesets to find the one matching the ruleset argument.
ceph osd pool set <pool> crush_ruleset must not use
CrushWrapper::rule_exists, which checks for a *rule* existing, whereas
the value being set is a *ruleset*. (cherry picked from commit
fb504baed98d57dca8ec141bcc3fd021f99d82b0)
A test via ceph osd pool set data crush_ruleset verifies the ruleset
argument is accepted.
http://tracker.ceph.com/issues/8599 fixes: #8599
Backport: firefly, emperor, dumpling
Signed-off-by: John Spray <john.spray@inktank.com>
Signed-off-by: Loic Dachary <loic@dachary.org>
fi
}
+#
+# Verify ceph osd pool set data crush_ruleset when
+# when ruleset != rule_id http://tracker.ceph.com/issues/8599
+#
+MAP=$TMPFILE.map.$$
+ceph osd getcrushmap -o $MAP
+[ -s $MAP ]
+crushtool --decompile $MAP -o $MAP.decompiled
+RULESET=55
+cat >> $MAP.decompiled <<EOF
+rule testrule1 {
+ ruleset $RULESET
+ type replicated
+ min_size 1
+ max_size 10
+ step take default
+ step choose firstn 0 type osd
+ step emit
+}
+EOF
+crushtool --compile $MAP.decompiled -o $MAP.modified
+ceph osd setcrushmap -i $MAP.modified
+ceph osd pool set data crush_ruleset $RULESET
+ceph osd pool set data crush_ruleset 0
+rm $MAP{,.decompiled,.modified}
# tiering
ceph osd pool create cache 2
if (!crush) return -1;
return crush_find_rule(crush, ruleset, type, size);
}
+
+ bool ruleset_exists(int ruleset) const {
+ for (size_t i = 0; i < crush->max_rules; ++i) {
+ if (crush->rules[i]->mask.ruleset == ruleset) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
void do_rule(int rule, int x, vector<int>& out, int maxout,
const vector<__u32>& weight) const {
Mutex::Locker l(mapper_lock);
ss << "error parsing integer value '" << val << "': " << interr;
return -EINVAL;
}
- if (!osdmap.crush->rule_exists(n)) {
+ if (!osdmap.crush->ruleset_exists(n)) {
ss << "crush ruleset " << n << " does not exist";
return -ENOENT;
}