The swap method is just swap the two buckets'weight,son and name.So there is a problem when we swap parent and children. When swap two buckets,one should not be ancestor of the other,or there will be a loop,which would destory the structure.
Signed-off-by: Carudy <zhaoyang.han@easystack.cn>
return bucket_weight;
}
+bool CrushWrapper::is_parent_of(int child, int p) const
+{
+ int parent = 0;
+ while (!get_immediate_parent_id(child, &parent)) {
+ if (parent == p) {
+ return true;
+ }
+ child = parent;
+ }
+ return false;
+}
+
int CrushWrapper::swap_bucket(CephContext *cct, int src, int dst)
{
if (src >= 0 || dst >= 0)
return -EINVAL;
crush_bucket *a = get_bucket(src);
crush_bucket *b = get_bucket(dst);
+ if (is_parent_of(a->id, b->id) || is_parent_of(b->id, a->id)) {
+ return -EINVAL;
+ }
unsigned aw = a->weight;
unsigned bw = b->weight;
* @return true if present
*/
bool _search_item_exists(int i) const;
+ bool is_parent_of(int child, int p) const;
public:
/**
ASSERT_EQ(1, c->get_bucket_item(a, 1));
ASSERT_EQ(2, c->get_bucket_item(a, 2));
ASSERT_EQ(3, c->get_bucket_item(b, 0));
+
+ // check if it can swap parent with child
+ ASSERT_EQ(-EINVAL, c->swap_bucket(g_ceph_context, root, a));
c->swap_bucket(g_ceph_context, a, b);
ASSERT_EQ(0x30000, c->get_item_weight(b));