]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: add dirfrag split/merge asok commands 4969/head
authorJohn Spray <john.spray@redhat.com>
Mon, 15 Jun 2015 13:16:08 +0000 (14:16 +0100)
committerJohn Spray <john.spray@redhat.com>
Mon, 15 Jun 2015 13:17:18 +0000 (14:17 +0100)
Analogous to those from the old-style mds tell.  Also
add an 'ls' that gives you the frags in the same format
that frag_t::parse expects them, so that it's a bit
less obscure to use.

Signed-off-by: John Spray <john.spray@redhat.com>
src/mds/MDS.cc
src/mds/MDS.h

index 7462c82129bc0bc13335e9a011443bc0c93c9f4d..4401ec0d37eb93983da7dca8f7bcf3bc3382452d 100644 (file)
@@ -359,6 +359,15 @@ bool MDS::asok_command(string command, cmdmap_t& cmdmap, string format,
       mds_lock.Lock();
       mdcache->force_readonly();
       mds_lock.Unlock();
+    } else if (command == "dirfrag split") {
+      Mutex::Locker l(mds_lock);
+      command_dirfrag_split(cmdmap, ss);
+    } else if (command == "dirfrag merge") {
+      Mutex::Locker l(mds_lock);
+      command_dirfrag_merge(cmdmap, ss);
+    } else if (command == "dirfrag ls") {
+      Mutex::Locker l(mds_lock);
+      command_dirfrag_ls(cmdmap, ss, f);
     }
   }
   f->flush(ss);
@@ -591,6 +600,150 @@ int MDS::_command_export_dir(
   return 0;
 }
 
+CDir *MDS::_command_dirfrag_get(
+    const cmdmap_t &cmdmap,
+    std::ostream &ss)
+{
+  std::string path;
+  bool got = cmd_getval(g_ceph_context, cmdmap, "path", path);
+  if (!got) {
+    ss << "missing path argument";
+    return NULL;
+  }
+
+  std::string frag_str;
+  if (!cmd_getval(g_ceph_context, cmdmap, "frag", frag_str)) {
+    ss << "missing frag argument";
+    return NULL;
+  }
+
+  CInode *in = mdcache->cache_traverse(filepath(path.c_str()));
+  if (!in) {
+    // TODO really we should load something in if it's not in cache,
+    // but the infrastructure is harder, and we might still be unable
+    // to act on it if someone else is auth.
+    ss << "directory inode not in cache";
+    return NULL;
+  }
+
+  frag_t fg;
+
+  if (!fg.parse(frag_str.c_str())) {
+    ss << "frag " << frag_str << " failed to parse";
+    return NULL;
+  }
+
+  CDir *dir = in->get_dirfrag(fg);
+  if (!dir) {
+    ss << "frag 0x" << std::hex << in->ino() << "/" << fg << " not found";
+    return NULL;
+  }
+
+  if (!dir->is_auth()) {
+    ss << "frag " << dir->dirfrag() << " not auth (auth = "
+       << dir->authority() << ")";
+    return NULL;
+  }
+
+  return dir;
+}
+
+bool MDS::command_dirfrag_split(
+    cmdmap_t cmdmap,
+    std::ostream &ss)
+{
+  int64_t by = 0;
+  if (!cmd_getval(g_ceph_context, cmdmap, "bits", by)) {
+    ss << "missing bits argument";
+    return false;
+  }
+
+  if (by <= 0) {
+    ss << "must split by >0 bits";
+    return false;
+  }
+
+  CDir *dir = _command_dirfrag_get(cmdmap, ss);
+  if (!dir) {
+    return false;
+  }
+
+  mdcache->split_dir(dir, by);
+
+  return true;
+}
+
+bool MDS::command_dirfrag_merge(
+    cmdmap_t cmdmap,
+    std::ostream &ss)
+{
+  std::string path;
+  bool got = cmd_getval(g_ceph_context, cmdmap, "path", path);
+  if (!got) {
+    ss << "missing path argument";
+    return false;
+  }
+
+  std::string frag_str;
+  if (!cmd_getval(g_ceph_context, cmdmap, "frag", frag_str)) {
+    ss << "missing frag argument";
+    return false;
+  }
+
+  CInode *in = mdcache->cache_traverse(filepath(path.c_str()));
+  if (!in) {
+    ss << "directory inode not in cache";
+    return false;
+  }
+
+  frag_t fg;
+  if (!fg.parse(frag_str.c_str())) {
+    ss << "frag " << frag_str << " failed to parse";
+    return false;
+  }
+
+  mdcache->merge_dir(in, fg);
+
+  return true;
+}
+
+bool MDS::command_dirfrag_ls(
+    cmdmap_t cmdmap,
+    std::ostream &ss,
+    Formatter *f)
+{
+  std::string path;
+  bool got = cmd_getval(g_ceph_context, cmdmap, "path", path);
+  if (!got) {
+    ss << "missing path argument";
+    return false;
+  }
+
+  CInode *in = mdcache->cache_traverse(filepath(path.c_str()));
+  if (!in) {
+    ss << "directory inode not in cache";
+    return false;
+  }
+
+  f->open_array_section("frags");
+  std::list<frag_t> frags;
+  // NB using get_leaves_under instead of get_dirfrags to give
+  // you the list of what dirfrags may exist, not which are in cache
+  in->dirfragtree.get_leaves_under(frag_t(), frags);
+  for (std::list<frag_t>::iterator i = frags.begin();
+       i != frags.end(); ++i) {
+    f->open_object_section("frag");
+    f->dump_int("value", i->value());
+    f->dump_int("bits", i->bits());
+    std::ostringstream frag_str;
+    frag_str << std::hex << i->value() << "/" << std::dec << i->bits();
+    f->dump_string("str", frag_str.str());
+    f->close_section();
+  }
+  f->close_section();
+
+  return true;
+}
 
 void MDS::set_up_admin_socket()
 {
@@ -664,6 +817,27 @@ void MDS::set_up_admin_socket()
                                     asok_hook,
                                     "Return the subtree map");
   assert(r == 0);
+  r = admin_socket->register_command("dirfrag split",
+                                    "dirfrag split "
+                                     "name=path,type=CephString,req=true "
+                                     "name=frag,type=CephString,req=true "
+                                     "name=bits,type=CephInt,req=true ",
+                                    asok_hook,
+                                    "Fragment directory by path");
+  assert(r == 0);
+  r = admin_socket->register_command("dirfrag merge",
+                                    "dirfrag merge "
+                                     "name=path,type=CephString,req=true "
+                                     "name=frag,type=CephString,req=true",
+                                    asok_hook,
+                                    "De-fragment directory by path");
+  assert(r == 0);
+  r = admin_socket->register_command("dirfrag ls",
+                                    "dirfrag ls "
+                                     "name=path,type=CephString,req=true",
+                                    asok_hook,
+                                    "List fragments in directory");
+  assert(r == 0);
 }
 
 void MDS::clean_up_admin_socket()
@@ -1257,7 +1431,7 @@ COMMAND("heap " \
        "mds", "*", "cli,rest")
 };
 
-// FIXME: reinstate issue_caps, try_eval, fragment_dir, merge_dir
+// FIXME: reinstate issue_caps, try_eval,
 //  *if* it makes sense to do so (or should these be admin socket things?)
 
 /* This function DOES put the passed message before returning*/
index f7335e46bca13cc851c9db52ffc4a3a0442b3646..c120dea10fa5836a8ce8dc7773b0bdf58a5a8e2e 100644 (file)
@@ -382,9 +382,22 @@ private:
   void command_get_subtrees(Formatter *f);
   void command_export_dir(Formatter *f,
       const std::string &path, mds_rank_t dest);
+  bool command_dirfrag_split(
+      cmdmap_t cmdmap,
+      std::ostream &ss);
+  bool command_dirfrag_merge(
+      cmdmap_t cmdmap,
+      std::ostream &ss);
+  bool command_dirfrag_ls(
+      cmdmap_t cmdmap,
+      std::ostream &ss,
+      Formatter *f);
  private:
   int _command_export_dir(const std::string &path, mds_rank_t dest);
   int _command_flush_journal(std::stringstream *ss);
+  CDir *_command_dirfrag_get(
+      const cmdmap_t &cmdmap,
+      std::ostream &ss);
  public:
     // config observer bits
   virtual const char** get_tracked_conf_keys() const;