}
+int CrushWrapper::remove_device(int item)
+{
+ cout << "remove_device item" << std::endl;
+
+ crush_bucket *was_bucket = 0;
+ int ret = -ENOENT;
+
+ set<int> roots;
+ find_roots(roots);
+ for (set<int>::iterator p = roots.begin(); p != roots.end(); ++p) {
+ list<int> q;
+ q.push_back(*p);
+ while (!q.empty()) {
+ int id = q.front();
+ q.pop_front();
+
+ if (id >= 0)
+ continue; // it's a leaf.
+
+ crush_bucket *b = get_bucket(id);
+ if (!b) {
+ cout << "remove_device warning: bad reference to bucket " << id << std::endl;
+ continue;
+ }
+
+ for (unsigned i=0; i<b->size; ++i) {
+ int id = b->items[i];
+ if (id == item) {
+ if (item < 0) {
+ crush_bucket *t = get_bucket(item);
+ if (t && t->size) {
+ cout << "remove_device bucket " << item << " has " << t->size << " items, not empty" << std::endl;
+ return -ENOTEMPTY;
+ }
+ was_bucket = t;
+ }
+ cout << "remove_device removing item " << item << " from bucket " << b->id << std::endl;
+ crush_bucket_remove_item(b, item);
+ ret = 0;
+ }
+ if (id < 0)
+ q.push_front(id);
+ }
+ }
+ }
+
+ if (was_bucket) {
+ cout << "remove_device removing bucket " << item << std::endl;
+ crush_remove_bucket(crush, was_bucket);
+ }
+
+ return ret;
+}
+
int CrushWrapper::insert_device(int item, int weight, string name,
map<string,string>& loc) // typename -> bucketname
{
cout << "insert_device adding " << item << " weight " << weight
<< " to bucket " << id << std::endl;
- crush_bucket *b = (crush_bucket *)get_bucket(id);
+ crush_bucket *b = get_bucket(id);
assert(b);
crush_bucket_add_item(b, item, 0);
adjust_item_weight(item, weight);
for (set<int>::iterator p = roots.begin(); p != roots.end(); p++) {
if (*p >= 0)
continue;
- crush_bucket *b = (struct crush_bucket *)get_bucket(*p);
+ crush_bucket *b = get_bucket(*p);
cout << "reweight bucket " << *p << std::endl;
crush_reweight_bucket(crush, b);
}
void find_roots(set<int>& roots) const;
int insert_device(int id, int weight, string name, map<string,string>& loc);
+ int remove_device(int id);
void adjust_item_weight(int id, int weight);
void reweight();
return (crush_bucket *)(-ENOENT);
return ret;
}
+ crush_bucket *get_bucket(int id) {
+ if (!crush)
+ return (crush_bucket *)(-EINVAL);
+ unsigned int pos = (unsigned int)(-1 - id);
+ unsigned int max_buckets = crush->max_buckets;
+ if (pos >= max_buckets)
+ return (crush_bucket *)(-ENOENT);
+ crush_bucket *ret = crush->buckets[pos];
+ if (ret == NULL)
+ return (crush_bucket *)(-ENOENT);
+ return ret;
+ }
public:
int get_max_buckets() const {
crush_bucket *b = crush_make_bucket(alg, hash, type, size, items, weights);
return crush_add_bucket(crush, bucketno, b);
}
-
+
void finalize() {
assert(crush);
crush_finalize(crush);
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
+#include <errno.h>
#include "builder.h"
#include "hash.h"
return id;
}
+int crush_remove_bucket(struct crush_map *map, struct crush_bucket *bucket)
+{
+ int pos = -1 - bucket->id;
+
+ map->buckets[pos] = NULL;
+ crush_destroy_bucket(bucket);
+ return 0;
+}
+
/* uniform bucket */
return 0;
}
+/************************************************/
+
+int crush_remove_uniform_bucket_item(struct crush_bucket_uniform *bucket, int item)
+{
+ int i, j;
+ int newsize;
+
+ for (i = 0; i < bucket->h.size; i++)
+ if (bucket->h.items[i] == item)
+ break;
+ if (i == bucket->h.size)
+ return -ENOENT;
+
+ for (j = i; j < bucket->h.size; j++)
+ bucket->h.items[j] = bucket->h.items[j+1];
+ newsize = --bucket->h.size;
+ bucket->h.weight -= bucket->item_weight;
+
+ bucket->h.items = realloc(bucket->h.items, sizeof(__u32)*newsize);
+ bucket->h.perm = realloc(bucket->h.perm, sizeof(__u32)*newsize);
+ return 0;
+}
+
+int crush_remove_list_bucket_item(struct crush_bucket_list *bucket, int item)
+{
+ int i, j;
+ int newsize;
+ int weight;
+
+ for (i = 0; i < bucket->h.size; i++)
+ if (bucket->h.items[i] == item)
+ break;
+ if (i == bucket->h.size)
+ return -ENOENT;
+
+ weight = bucket->item_weights[i];
+ for (j = i; j < bucket->h.size; j++) {
+ bucket->h.items[j] = bucket->h.items[j+1];
+ bucket->item_weights[j] = bucket->item_weights[j+1];
+ bucket->sum_weights[j] = bucket->sum_weights[j+1] - weight;
+ }
+ bucket->h.weight -= weight;
+ newsize = --bucket->h.size;
+
+ bucket->h.items = realloc(bucket->h.items, sizeof(__u32)*newsize);
+ bucket->h.perm = realloc(bucket->h.perm, sizeof(__u32)*newsize);
+ bucket->item_weights = realloc(bucket->item_weights, sizeof(__u32)*newsize);
+ bucket->sum_weights = realloc(bucket->sum_weights, sizeof(__u32)*newsize);
+ return 0;
+}
+
+int crush_remove_tree_bucket_item(struct crush_bucket_tree *bucket, int item)
+{
+ int i;
+ int newsize;
+
+ for (i = 0; i < bucket->h.size; i++) {
+ int node;
+ int weight;
+ int j;
+ int depth = calc_depth(bucket->h.size);
+
+ if (bucket->h.items[i] != item)
+ continue;
+
+ node = crush_calc_tree_node(i);
+ weight = bucket->node_weights[node];
+ bucket->node_weights[node] = 0;
+
+ for (j = 1; j < depth; j++) {
+ node = parent(node);
+ bucket->node_weights[node] -= weight;
+ printf(" node %d weight %d\n", node, bucket->node_weights[node]);
+ }
+ bucket->h.weight -= weight;
+ break;
+ }
+ if (i == bucket->h.size)
+ return -ENOENT;
+
+ newsize = bucket->h.size;
+ while (newsize > 0) {
+ int node = crush_calc_tree_node(newsize - 1);
+ if (bucket->node_weights[node])
+ break;
+ --newsize;
+ }
+
+ if (newsize != bucket->h.size) {
+ int olddepth, newdepth;
+
+ bucket->h.items = realloc(bucket->h.items, sizeof(__u32)*newsize);
+ bucket->h.perm = realloc(bucket->h.perm, sizeof(__u32)*newsize);
+
+ olddepth = calc_depth(bucket->h.size);
+ newdepth = calc_depth(newsize);
+ if (olddepth != newdepth) {
+ bucket->num_nodes = 1 << newdepth;
+ bucket->node_weights = realloc(bucket->node_weights,
+ sizeof(__u32)*bucket->num_nodes);
+ }
+
+ bucket->h.size = newsize;
+ }
+ return 0;
+}
+
+int crush_remove_straw_bucket_item(struct crush_bucket_straw *bucket, int item)
+{
+ int newsize = bucket->h.size - 1;
+ int i, j;
+
+ for (i = 0; i < bucket->h.size; i++) {
+ if (bucket->h.items[i] == item) {
+ bucket->h.size--;
+ bucket->h.weight -= bucket->item_weights[i];
+ for (j = i; j < bucket->h.size; j++) {
+ bucket->h.items[j] = bucket->h.items[j+1];
+ bucket->item_weights[j] = bucket->item_weights[j+1];
+ }
+ break;
+ }
+ }
+ if (i == bucket->h.size)
+ return -ENOENT;
+
+ bucket->h.items = realloc(bucket->h.items, sizeof(__u32)*newsize);
+ bucket->h.perm = realloc(bucket->h.perm, sizeof(__u32)*newsize);
+ bucket->item_weights = realloc(bucket->item_weights, sizeof(__u32)*newsize);
+ bucket->straws = realloc(bucket->straws, sizeof(__u32)*newsize);
+
+ return crush_calc_straw(bucket);
+}
+
+int crush_bucket_remove_item(struct crush_bucket *b, int item)
+{
+ /* invalidate perm cache */
+ b->perm_n = 0;
+
+ switch (b->alg) {
+ case CRUSH_BUCKET_UNIFORM:
+ return crush_remove_uniform_bucket_item((struct crush_bucket_uniform *)b, item);
+ case CRUSH_BUCKET_LIST:
+ return crush_remove_list_bucket_item((struct crush_bucket_list *)b, item);
+ case CRUSH_BUCKET_TREE:
+ return crush_remove_tree_bucket_item((struct crush_bucket_tree *)b, item);
+ case CRUSH_BUCKET_STRAW:
+ return crush_remove_straw_bucket_item((struct crush_bucket_straw *)b, item);
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+
/************************************************/
int crush_adjust_uniform_bucket_item_weight(struct crush_bucket_uniform *bucket, int item, int weight)
}
return 0;
}
+
+/***************************/
+
float add_weight = 0;
const char *add_name = 0;
map<string,string> add_loc;
+ const char *remove_name = 0;
int build = 0;
int num_osds =0;
CEPH_ARGPARSE_SET_ARG_VAL(&type, OPT_STR);
CEPH_ARGPARSE_SET_ARG_VAL(&name, OPT_STR);
add_loc[type] = name;
+ } else if (CEPH_ARGPARSE_EQ("remove_item", '\0')) {
+ CEPH_ARGPARSE_SET_ARG_VAL(&remove_name, OPT_STR);
} else if (CEPH_ARGPARSE_EQ("verbose", 'v')) {
verbose++;
} else if (CEPH_ARGPARSE_EQ("build", '\0')) {
}
if (decompile + compile + build > 1)
usage();
- if (!compile && !decompile && !build && !test && !reweight && add_item < 0)
+ if (!compile && !decompile && !build && !test && !reweight && add_item < 0 && !remove_name)
usage();
/*
modified = true;
}
+ if (remove_name) {
+ cout << me << " removing item " << remove_name << std::endl;
+ int r;
+ if (!crush.name_exists(remove_name)) {
+ cerr << " name " << remove_name << " dne" << std::endl;
+ r = -ENOENT;
+ } else {
+ int remove_item = crush.get_item_id(remove_name);
+ r = crush.remove_device(remove_item);
+ }
+ if (r == 0)
+ modified = true;
+ else {
+ cerr << me << " " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+ }
if (add_item >= 0) {
cout << me << " adding item " << add_item << " weight " << add_weight
<< " at " << add_loc << std::endl;