diff --git a/qa/workunits/mon/crush_ops.sh b/qa/workunits/mon/crush_ops.sh index c1aa54b08ae..a3f189e8a27 100755 --- a/qa/workunits/mon/crush_ops.sh +++ b/qa/workunits/mon/crush_ops.sh @@ -104,6 +104,7 @@ o3=`ceph osd create` ceph osd crush add $o3 123 root=default ceph osd tree | grep osd.$o3 | grep 123 ceph osd crush reweight osd.$o3 113 +expect_false ceph osd crush reweight osd.$o3 123456 ceph osd tree | grep osd.$o3 | grep 113 ceph osd crush rm osd.$o3 ceph osd rm osd.$o3 @@ -116,6 +117,7 @@ ceph osd crush add $o5 123 root=default host=foobaz ceph osd tree | grep osd.$o4 | grep 123 ceph osd tree | grep osd.$o5 | grep 123 ceph osd crush reweight-subtree foobaz 155 +expect_false ceph osd crush reweight-subtree foobaz 123456 ceph osd tree | grep osd.$o4 | grep 155 ceph osd tree | grep osd.$o5 | grep 155 ceph osd crush rm osd.$o4 diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 6a0017df96d..425ec311f7f 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -807,6 +807,11 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n if (!is_valid_crush_loc(cct, loc)) return -EINVAL; + int r = validate_weightf(weight); + if (r < 0) { + return r; + } + if (name_exists(name)) { if (get_item_id(name) != item) { ldout(cct, 10) << "device name '" << name << "' already exists as id " @@ -1021,6 +1026,11 @@ int CrushWrapper::update_item(CephContext *cct, int item, float weight, string n if (!is_valid_crush_loc(cct, loc)) return -EINVAL; + ret = validate_weightf(weight); + if (ret < 0) { + return ret; + } + // compare quantized (fixed-point integer) weights! int iweight = (int)(weight * (float)0x10000); int old_iweight; diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index b5bfebb7657..3f181e2eeb7 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -849,18 +849,37 @@ public: return (float)get_item_weight_in_loc(id, loc) / (float)0x10000; } + int validate_weightf(float weight) { + uint64_t iweight = weight * 0x10000; + if (iweight > std::numeric_limits::max()) { + return -EOVERFLOW; + } + return 0; + } int adjust_item_weight(CephContext *cct, int id, int weight); int adjust_item_weightf(CephContext *cct, int id, float weight) { + int r = validate_weightf(weight); + if (r < 0) { + return r; + } return adjust_item_weight(cct, id, (int)(weight * (float)0x10000)); } int adjust_item_weight_in_loc(CephContext *cct, int id, int weight, const map& loc); int adjust_item_weightf_in_loc(CephContext *cct, int id, float weight, const map& loc) { + int r = validate_weightf(weight); + if (r < 0) { + return r; + } return adjust_item_weight_in_loc(cct, id, (int)(weight * (float)0x10000), loc); } void reweight(CephContext *cct); int adjust_subtree_weight(CephContext *cct, int id, int weight); int adjust_subtree_weightf(CephContext *cct, int id, float weight) { + int r = validate_weightf(weight); + if (r < 0) { + return r; + } return adjust_subtree_weight(cct, id, (int)(weight * (float)0x10000)); }