summaryrefslogtreecommitdiffstats
path: root/src/crush
diff options
context:
space:
mode:
authorSage Weil <sage@redhat.com>2017-05-12 23:39:14 +0200
committerSage Weil <sage@redhat.com>2017-05-15 15:15:58 +0200
commit5f795631973407fc9ee39f3c52e7f905e4711ff8 (patch)
treeb766a9c4948baed8d907d4caeab7e38149519f74 /src/crush
parentMerge pull request #13111 from cbodley/wip-rgw-mdlog-trim (diff)
downloadceph-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.cc46
-rw-r--r--src/crush/CrushWrapper.h20
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