From a2d0cff1b071bed84ac439e4fcf9ddfb936f89c8 Mon Sep 17 00:00:00 2001 From: Caleb Miles Date: Fri, 29 Jun 2012 10:54:16 -0700 Subject: [PATCH] crush: add move_bucket() method Move an existing bucket to a new location in the hierarchy. Signed-off-by: Caleb Miles --- src/crush/CrushWrapper.cc | 25 +++++++++++++++++ src/crush/CrushWrapper.h | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 63a3374696682..9c6deba32a18b 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -186,6 +186,31 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n return -EINVAL; } +int CrushWrapper::move_bucket(CephContext *cct, int id, map& loc) +{ + // sorry this only works for buckets + if (id >= 0) + return -EINVAL; + + if (!item_exists(id)) + return -ENOENT; + + // get the name of the bucket we are trying to move for later + string id_name = get_item_name(id); + + // detach the bucket + int bucket_weight = detach_bucket(cct, id); + + // un-set the device name so we can use add_item later + build_rmap(name_map, name_rmap); + name_map.erase(id); + name_rmap.erase(id_name); + + // insert the bucket back into the hierarchy + return insert_item(cct, id, bucket_weight / (float)0x10000, id_name, loc); +} + + int CrushWrapper::update_item(CephContext *cct, int item, float weight, string name, map& loc) // typename -> bucketname { diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index 6f86a2d919d68..8475741656306 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -252,6 +252,19 @@ public: */ int insert_item(CephContext *cct, int id, float weight, string name, map& loc); + /** + * move a bucket in the hierarchy to the given location + * + * This has the same location and ancestor creation behavior as + * insert_item(), but will relocate the specified existing bucket. + * + * @param cct cct + * @param id bucket id + * @param loc location (map of type to bucket names) + * @return 0 for success, negative on error + */ + int move_bucket(CephContext *cct, int id, map& loc); + /** * add or update an item's position in the map * @@ -423,6 +436,51 @@ private: return (crush_bucket *)(-ENOENT); return ret; } + /** + * detach a bucket from its parent and adjust the parent weight + * + * returns the weight of the detached bucket + **/ + int detach_bucket(CephContext *cct, int item){ + if (!crush) + return (-EINVAL); + + if (item > 0) + return (-EINVAL); + + // check that the bucket that we want to detach exists + assert( get_bucket(item) ); + + // get the bucket's weight + crush_bucket *b = get_bucket(item); + unsigned bucket_weight = b->weight; + + // zero out the bucket weight + adjust_item_weight(cct, item, 0); + + // get where the bucket is located + pair bucket_location = get_immediate_parent(item); + + // get the id of the parent bucket + int parent_id = get_item_id( (bucket_location.second).c_str() ); + + // get the parent bucket + crush_bucket *parent_bucket = get_bucket(parent_id); + + // remove the bucket from the parent + crush_bucket_remove_item(parent_bucket, item); + + // check that we're happy + int test_weight = 0; + map test_location; + test_location[ bucket_location.first ] = (bucket_location.second); + + bool successful_detach = !(check_item_loc(cct, item, test_location, &test_weight)); + assert(successful_detach); + assert(test_weight == 0); + + return bucket_weight; + } public: int get_max_buckets() const { -- 2.39.5