]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/crush/CrushWrapper.h
update sources to v12.1.1
[ceph.git] / ceph / src / crush / CrushWrapper.h
index c47a5badc412854f13db0846505e0912c142f6f3..5fd35a88ad9ce1661ea0187eefc2612434682e72 100644 (file)
@@ -20,13 +20,13 @@ extern "C" {
 #include "builder.h"
 }
 
+#include "include/assert.h"
 #include "include/err.h"
 #include "include/encoding.h"
 
 
 #include "common/Mutex.h"
 
-#include "include/assert.h"
 #define BUG_ON(x) assert(!(x))
 
 namespace ceph {
@@ -62,6 +62,9 @@ public:
 
 private:
   struct crush_map *crush;
+
+  bool have_uniform_rules = false;
+
   /* reverse maps */
   mutable bool have_rmaps;
   mutable std::map<string, int> type_rmap, name_rmap, rule_name_rmap;
@@ -105,6 +108,15 @@ public:
     set_tunables_default();
   }
 
+  /// true if any rule has a ruleset != the rule id
+  bool has_legacy_rulesets() const;
+
+  /// fix rules whose ruleid != ruleset
+  int renumber_rules_by_ruleset();
+
+  /// true if any ruleset has more than 1 rule
+  bool has_multirule_rulesets() const;
+
   // tunables
   void set_tunables_argonaut() {
     crush->choose_local_tries = 2;
@@ -169,7 +181,7 @@ public:
     crush->straw_calc_version = 1;
   }
   void set_tunables_default() {
-    set_tunables_hammer();
+    set_tunables_jewel();
     crush->straw_calc_version = 1;
   }
 
@@ -316,8 +328,8 @@ public:
   bool has_v3_rules() const;
   bool has_v4_buckets() const;
   bool has_v5_rules() const;
-  bool has_chooseargs() const;          // any chooseargs
-  bool has_incompat_chooseargs() const; // chooseargs that can't be made compat
+  bool has_choose_args() const;          // any choose_args
+  bool has_incompat_choose_args() const; // choose_args that can't be made compat
 
   bool is_v2_rule(unsigned ruleid) const;
   bool is_v3_rule(unsigned ruleid) const;
@@ -356,6 +368,11 @@ public:
   int get_num_type_names() const {
     return type_map.size();
   }
+  int get_max_type_id() const {
+    if (type_map.empty())
+      return 0;
+    return type_map.rbegin()->first;
+  }
   int get_type_id(const string& name) const {
     build_rmaps();
     if (type_rmap.count(name))
@@ -402,6 +419,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;
@@ -415,34 +442,52 @@ public:
     return class_rname.count(name);
   }
   const char *get_class_name(int i) const {
-    std::map<int,string>::const_iterator p = class_name.find(i);
+    auto p = class_name.find(i);
     if (p != class_name.end())
       return p->second.c_str();
     return 0;
   }
   int get_class_id(const string& name) const {
-    std::map<string,int>::const_iterator p = class_rname.find(name);
+    auto p = class_rname.find(name);
     if (p != class_rname.end())
       return p->second;
     else
       return -EINVAL;
   }
   int remove_class_name(const string& name) {
-    std::map<string,int>::const_iterator p = class_rname.find(name);
+    auto p = class_rname.find(name);
     if (p == class_rname.end())
       return -ENOENT;
     int class_id = p->second;
-    std::map<int,string>::const_iterator q = class_name.find(class_id);
+    auto q = class_name.find(class_id);
     if (q == class_name.end())
       return -ENOENT;
     class_rname.erase(name);
     class_name.erase(class_id);
     return 0;
   }
+
+  int rename_class(const string& srcname, const string& dstname) {
+    auto p = class_rname.find(srcname);
+    if (p == class_rname.end())
+      return -ENOENT;
+    int class_id = p->second;
+    auto q = class_name.find(class_id);
+    if (q == class_name.end())
+      return -ENOENT;
+    class_rname.erase(srcname);
+    class_name.erase(class_id);
+    class_rname[dstname] = class_id;
+    class_name[class_id] = dstname;
+    return 0;
+  }
+
+  int32_t _alloc_class_id() const;
+
   int get_or_create_class_id(const string& name) {
     int c = get_class_id(name);
     if (c < 0) {
-      int i = class_name.size();
+      int i = _alloc_class_id();
       class_name[i] = name;
       class_rname[name] = i;
       return i;
@@ -467,7 +512,26 @@ public:
     class_map[i] = c;
     return c;
   }
-
+  void get_devices_by_class(const string &name, set<int> *devices) const {
+    assert(devices);
+    devices->clear();
+    if (!class_exists(name)) {
+      return;
+    }
+    auto cid = get_class_id(name);
+    for (auto& p : class_map) {
+      if (p.first >= 0 && p.second == cid) {
+        devices->insert(p.first);
+      }
+    }
+  }
+  void class_remove_item(int i) {
+    auto it = class_map.find(i);
+    if (it == class_map.end()) {
+      return;
+    }
+    class_map.erase(it);
+  }
   int can_rename_item(const string& srcname,
                      const string& dstname,
                      ostream *ss) const;
@@ -519,6 +583,14 @@ public:
    */
   void find_roots(set<int>& roots) const;
 
+  /**
+   * find tree roots that are not shadow (device class) items
+   *
+   * These are parentless nodes in the map that are not shadow
+   * items for device classes.
+   */
+  void find_nonshadow_roots(set<int>& roots) const;
+
   /**
    * see if an item is contained within a subtree
    *
@@ -573,6 +645,12 @@ public:
   pair<string,string> get_immediate_parent(int id, int *ret = NULL);
   int get_immediate_parent_id(int id, int *parent) const;
 
+  /**
+   * return ancestor of the given type, or 0 if none
+   * (parent is always a bucket and thus <0)
+   */
+  int get_parent_of_type(int id, int type) const;
+
   /**
    * get the fully qualified location of a device by successively finding
    * parents beginning at ID and ending at highest type number specified in
@@ -592,6 +670,15 @@ public:
    */
   int get_full_location_ordered(int id, vector<pair<string, string> >& path);
 
+  /*
+   * identical to get_full_location_ordered(int id, vector<pair<string, string> >& path),
+   * although it returns a concatenated string with the type/name pairs in descending
+   * hierarchical order with format key1=val1,key2=val2.
+   *
+   * returns the location in descending hierarchy as a string.
+   */
+  string get_full_location_ordered_string(int id);
+
   /**
    * returns (type_id, type) of all parent buckets between id and
    * default, can be used to check for anomolous CRUSH maps
@@ -606,6 +693,15 @@ public:
    */
   int get_children(int id, list<int> *children);
 
+  /**
+    * enumerate leaves(devices) of given node
+    *
+    * @param name parent bucket name
+    * @return 0 on success or a negative errno on error.
+    */
+  int get_leaves(const string &name, set<int> *leaves);
+  int _get_leaves(int id, list<int> *leaves); // worker
+
   /**
    * insert an item into the map at a specific position
    *
@@ -651,6 +747,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
    *
@@ -772,18 +878,37 @@ public:
     return (float)get_item_weight_in_loc(id, loc) / (float)0x10000;
   }
 
+  int validate_weightf(float weight) {
+    uint64_t iweight = weight * 0x10000;
+    if (iweight > std::numeric_limits<int>::max()) {
+      return -EOVERFLOW;
+    }
+    return 0;
+  }
   int adjust_item_weight(CephContext *cct, int id, int weight);
   int adjust_item_weightf(CephContext *cct, int id, float weight) {
+    int r = validate_weightf(weight);
+    if (r < 0) {
+      return r;
+    }
     return adjust_item_weight(cct, id, (int)(weight * (float)0x10000));
   }
   int adjust_item_weight_in_loc(CephContext *cct, int id, int weight, const map<string,string>& loc);
   int adjust_item_weightf_in_loc(CephContext *cct, int id, float weight, const map<string,string>& loc) {
+    int r = validate_weightf(weight);
+    if (r < 0) {
+      return r;
+    }
     return adjust_item_weight_in_loc(cct, id, (int)(weight * (float)0x10000), loc);
   }
   void reweight(CephContext *cct);
 
   int adjust_subtree_weight(CephContext *cct, int id, int weight);
   int adjust_subtree_weightf(CephContext *cct, int id, float weight) {
+    int r = validate_weightf(weight);
+    if (r < 0) {
+      return r;
+    }
     return adjust_subtree_weight(cct, id, (int)(weight * (float)0x10000));
   }
 
@@ -936,14 +1061,18 @@ public:
     return set_rule_step(ruleno, step, CRUSH_RULE_EMIT, 0, 0);
   }
 
-  int add_simple_ruleset(string name, string root_name, string failure_domain_type,
-                        string mode, int rule_type, ostream *err = 0);
+  int add_simple_rule(
+    string name, string root_name, string failure_domain_type,
+    string device_class,
+    string mode, int rule_type, ostream *err = 0);
+
   /**
-   * @param rno ruleset id to use, -1 to pick the lowest available
+   * @param rno rule[set] id to use, -1 to pick the lowest available
    */
-  int add_simple_ruleset_at(string name, string root_name,
-                            string failure_domain_type, string mode,
-                            int rule_type, int rno, ostream *err = 0);
+  int add_simple_rule_at(
+    string name, string root_name,
+    string failure_domain_type, string device_class, string mode,
+    int rule_type, int rno, ostream *err = 0);
 
   int remove_rule(int ruleno);
 
@@ -1004,11 +1133,11 @@ private:
 
     if (!IS_ERR(parent_bucket)) {
       // zero out the bucket weight
-      crush_bucket_adjust_item_weight(crush, parent_bucket, item, 0);
+      bucket_adjust_item_weight(cct, parent_bucket, item, 0);
       adjust_item_weight(cct, parent_bucket->id, parent_bucket->weight);
 
       // remove the bucket from the parent
-      crush_bucket_remove_item(crush, parent_bucket, item);
+      bucket_remove_item(parent_bucket, item);
     } else if (PTR_ERR(parent_bucket) != -ENOENT) {
       return PTR_ERR(parent_bucket);
     }
@@ -1100,13 +1229,18 @@ public:
     assert(b);
     return crush_add_bucket(crush, bucketno, b, idout);
   }
-  
+
+  int bucket_add_item(crush_bucket *bucket, int item, int weight);
+  int bucket_remove_item(struct crush_bucket *bucket, int item);
+  int bucket_adjust_item_weight(CephContext *cct, struct crush_bucket *bucket, int item, int weight);
+
   void finalize() {
     assert(crush);
     crush_finalize(crush);
+    have_uniform_rules = !has_legacy_rulesets();
   }
 
-  int update_device_class(CephContext *cct, int id, const string& class_name, const string& name);
+  int update_device_class(int id, const string& class_name, const string& name, ostream *ss);
   int device_class_clone(int original, int device_class, int *clone);
   bool class_is_in_use(int class_id);
   int populate_classes();
@@ -1145,7 +1279,14 @@ public:
 
   int find_rule(int ruleset, int type, int size) const {
     if (!crush) return -1;
-    return crush_find_rule(crush, ruleset, type, size);
+    if (!have_uniform_rules) {
+      return crush_find_rule(crush, ruleset, type, size);
+    } else {
+      if (ruleset < (int)crush->max_rules &&
+         crush->rules[ruleset])
+       return ruleset;
+      return -1;
+    }
   }
 
   bool ruleset_exists(int const ruleset) const {
@@ -1284,8 +1425,6 @@ public:
   void dump_tree(Formatter *f) const;
   static void generate_test_instances(list<CrushWrapper*>& o);
 
-  int _get_osd_pool_default_crush_replicated_ruleset(CephContext *cct,
-                                                     bool quiet);
   int get_osd_pool_default_crush_replicated_ruleset(CephContext *cct);
 
   static bool is_valid_crush_name(const string& s);