diff options
author | Sage Weil <sage@redhat.com> | 2017-05-12 23:39:14 +0200 |
---|---|---|
committer | Sage Weil <sage@redhat.com> | 2017-05-15 15:15:58 +0200 |
commit | 5f795631973407fc9ee39f3c52e7f905e4711ff8 (patch) | |
tree | b766a9c4948baed8d907d4caeab7e38149519f74 /src/crush | |
parent | Merge pull request #13111 from cbodley/wip-rgw-mdlog-trim (diff) | |
download | ceph-5f795631973407fc9ee39f3c52e7f905e4711ff8.tar.xz ceph-5f795631973407fc9ee39f3c52e7f905e4711ff8.zip |
crush: implement swap_bucket
Swap contents between buckets.
Signed-off-by: Sage Weil <sage@redhat.com>
Diffstat (limited to 'src/crush')
-rw-r--r-- | src/crush/CrushWrapper.cc | 46 | ||||
-rw-r--r-- | src/crush/CrushWrapper.h | 20 |
2 files changed, 66 insertions, 0 deletions
diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index ee6db9bc629..b4319ce33e4 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -790,6 +790,52 @@ int CrushWrapper::move_bucket(CephContext *cct, int id, const map<string,string> return insert_item(cct, id, bucket_weight / (float)0x10000, id_name, loc); } +int CrushWrapper::swap_bucket(CephContext *cct, int src, int dst) +{ + if (src >= 0 || dst >= 0) + return -EINVAL; + if (!item_exists(src) || !item_exists(dst)) + return -EINVAL; + crush_bucket *a = get_bucket(src); + crush_bucket *b = get_bucket(dst); + unsigned aw = a->weight; + unsigned bw = b->weight; + + // swap weights + adjust_item_weight(cct, a->id, bw); + adjust_item_weight(cct, b->id, aw); + + // swap items + map<int,unsigned> tmp; + unsigned as = a->size; + unsigned bs = b->size; + for (unsigned i = 0; i < as; ++i) { + int item = a->items[0]; + int itemw = crush_get_bucket_item_weight(a, 0); + tmp[item] = itemw; + crush_bucket_remove_item(crush, a, item); + } + assert(a->size == 0); + assert(b->size == bs); + for (unsigned i = 0; i < bs; ++i) { + int item = b->items[0]; + int itemw = crush_get_bucket_item_weight(b, 0); + crush_bucket_remove_item(crush, b, item); + crush_bucket_add_item(crush, a, item, itemw); + } + assert(a->size == bs); + assert(b->size == 0); + for (auto t : tmp) { + crush_bucket_add_item(crush, b, t.first, t.second); + } + assert(a->size == bs); + assert(b->size == as); + + // swap names + swap_names(src, dst); + return 0; +} + int CrushWrapper::link_bucket(CephContext *cct, int id, const map<string,string>& loc) { if (choose_args.size() > 0) { diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index c47a5badc41..dde6d4c63c0 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -402,6 +402,16 @@ public: name_rmap[name] = i; return 0; } + void swap_names(int a, int b) { + string an = name_map[a]; + string bn = name_map[b]; + name_map[a] = bn; + name_map[b] = an; + if (have_rmaps) { + name_rmap[an] = b; + name_rmap[bn] = a; + } + } bool id_has_class(int i) { int idout; int classout; @@ -652,6 +662,16 @@ public: int move_bucket(CephContext *cct, int id, const map<string,string>& loc); /** + * swap bucket contents of two buckets without touching bucket ids + * + * @param cct cct + * @param src bucket a + * @param dst bucket b + * @return 0 for success, negative on error + */ + int swap_bucket(CephContext *cct, int src, int dst); + + /** * add a link to an existing bucket in the hierarchy to the new location * * This has the same location and ancestor creation behavior as |