]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: add dump_cache asok command
authorSage Weil <sage@inktank.com>
Mon, 12 Nov 2012 19:06:42 +0000 (11:06 -0800)
committerSage Weil <sage@inktank.com>
Mon, 12 Nov 2012 23:05:52 +0000 (15:05 -0800)
Signed-off-by: Sage Weil <sage@inktank.com>
src/Makefile.am
src/client/Client.cc
src/client/Client.h
src/client/Dentry.cc [new file with mode: 0644]
src/client/Dentry.h
src/client/Inode.cc
src/client/Inode.h
src/client/SnapRealm.cc [new file with mode: 0644]
src/client/SnapRealm.h

index e599d7c16db6a18f97f7d4ce632543f02a4a6d75..2acfd05b684d1054a19f395e7cecf5c56f34fa36 100644 (file)
@@ -1349,7 +1349,9 @@ noinst_LTLIBRARIES += libosdc.la
 libclient_la_SOURCES = \
        client/Client.cc \
        client/Inode.cc \
+       client/Dentry.cc \
        client/MetaRequest.cc \
+       client/SnapRealm.cc \
        client/Trace.cc
 libclient_la_LIBADD = libosdc.la $(LIBEDIT_LIBS)
 noinst_LTLIBRARIES += libclient.la
index 0dbc489209f863a0260ce041b5706359d4bd6193..6a6d656196f039839d996f1b964eca951a579a36 100644 (file)
@@ -115,6 +115,8 @@ bool Client::CommandHook::call(std::string command, std::string args, bufferlist
   m_client->client_lock.Lock();
   if (command == "mds_requests")
     m_client->dump_mds_requests(&formatter);
+  else if (command == "dump_cache")
+    m_client->dump_cache(&formatter);
   else
     assert(0 == "bad command registered");
   m_client->client_lock.Unlock();
@@ -258,7 +260,7 @@ inodeno_t Client::get_root_ino()
 
 // debug crapola
 
-void Client::dump_inode(Inode *in, set<Inode*>& did, bool disconnected)
+void Client::dump_inode(Formatter *f, Inode *in, set<Inode*>& did, bool disconnected)
 {
   filepath path;
   in->make_long_path(path);
@@ -268,6 +270,16 @@ void Client::dump_inode(Inode *in, set<Inode*>& did, bool disconnected)
                << " " << path
                << " ref " << in->get_num_ref()
                << *in << dendl;
+
+  if (f) {
+    f->open_object_section("inode");
+    f->dump_stream("path") << path;
+    if (disconnected)
+      f->dump_int("disconnected", 1);
+    in->dump(f);
+    f->close_section();
+  }
+
   did.insert(in);
   if (in->dir) {
     ldout(cct, 1) << "  dir " << in->dir << " size " << in->dir->dentries.size() << dendl;
@@ -275,19 +287,27 @@ void Client::dump_inode(Inode *in, set<Inode*>& did, bool disconnected)
          it != in->dir->dentries.end();
          it++) {
       ldout(cct, 1) << "   " << in->ino << " dn " << it->first << " " << it->second << " ref " << it->second->ref << dendl;
-      dump_inode(it->second->inode, did, false);
+      if (f) {
+       f->open_object_section("dentry");
+       it->second->dump(f);
+       f->close_section();
+      }        
+      dump_inode(f, it->second->inode, did, false);
     }
   }
 }
 
-void Client::dump_cache()
+void Client::dump_cache(Formatter *f)
 {
   set<Inode*> did;
 
   ldout(cct, 1) << "dump_cache" << dendl;
 
+  if (f)
+    f->open_array_section("cache");
+
   if (root)
-    dump_inode(root, did, true);
+    dump_inode(f, root, did, true);
 
   // make a second pass to catch anything disconnected
   for (hash_map<vinodeno_t, Inode*>::iterator it = inode_map.begin();
@@ -295,8 +315,11 @@ void Client::dump_cache()
        it++) {
     if (did.count(it->second))
       continue;
-    dump_inode(it->second, did, true);
+    dump_inode(f, it->second, did, true);
   }
+
+  if (f)
+    f->close_section();
 }
 
 int Client::init()
@@ -348,6 +371,13 @@ int Client::init()
     lderr(cct) << "error registering admin socket command: "
               << cpp_strerror(-ret) << dendl;
   }
+  ret = admin_socket->register_command("dump_cache",
+                                      &m_command_hook,
+                                      "show in-memory metadata cache contents");
+  if (ret < 0) {
+    lderr(cct) << "error registering admin socket command: "
+              << cpp_strerror(-ret) << dendl;
+  }
 
   client_lock.Unlock();
   return r;
@@ -1637,7 +1667,7 @@ bool Client::ms_dispatch(Message *m)
     } else {
       ldout(cct, 10) << "unmounting: trim pass, size still " << lru.lru_get_size() 
                << "+" << inode_map.size() << dendl;
-      dump_cache();      
+      dump_cache(NULL);      
     }
   }
 
@@ -3529,7 +3559,7 @@ void Client::unmount()
             << "+" << inode_map.size() << " items" 
            << ", waiting (for caps to release?)"
             << dendl;
-    dump_cache();
+    dump_cache(NULL);
     mount_cond.Wait(client_lock);
   }
   assert(lru.lru_get_size() == 0);
index d261388c83345a56de247434b8e03cc67fe9b012..840124d741b2c260685e7ea00fe9fc5fd64432ae 100644 (file)
@@ -370,8 +370,8 @@ protected:
   void trim_dentry(Dentry *dn);
   void trim_caps(int mds, int max);
   
-  void dump_inode(Inode *in, set<Inode*>& did, bool disconnected);
-  void dump_cache();  // debug
+  void dump_inode(Formatter *f, Inode *in, set<Inode*>& did, bool disconnected);
+  void dump_cache(Formatter *f);  // debug
   
   // trace generation
   ofstream traceout;
diff --git a/src/client/Dentry.cc b/src/client/Dentry.cc
new file mode 100644 (file)
index 0000000..8bb21ac
--- /dev/null
@@ -0,0 +1,28 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "include/types.h"
+#include "include/utime.h"
+
+#include "Dentry.h"
+#include "Dir.h"
+#include "Inode.h"
+
+#include "common/Formatter.h"
+
+void Dentry::dump(Formatter *f) const
+{
+  f->dump_string("name", name);
+  f->dump_stream("dir") << dir->parent_inode->ino;
+  if (inode)
+    f->dump_stream("ino") << inode->ino;
+  f->dump_int("ref", ref);
+  f->dump_unsigned("offset", offset);
+  if (lease_mds >= 0) {
+    f->dump_int("lease_mds", lease_mds);
+    f->dump_stream("lease_ttl") << lease_ttl;
+    f->dump_int("lease_gen", lease_gen);
+    f->dump_int("lease_seq", lease_seq);
+  }
+  f->dump_int("cap_shared_gen", cap_shared_gen);
+}
index 701a0f7785752f2110f386a9d43f7398531feba6..932f17dbafca587022d4be09beda591a23ea4865 100644 (file)
@@ -38,6 +38,8 @@ class Dentry : public LRUObject {
     if (ref == 0)
       delete this;
   }
+
+  void dump(Formatter *f) const;
   
   Dentry() : dir(0), inode(0), ref(1), offset(0), lease_mds(-1), lease_gen(0), lease_seq(0), cap_shared_gen(0) { }
 private:
index 3d669d6ec42eec031d137fbecb03b987923fb619..0dfd1ebdce80393a815079d28212097b3fc5d5c4 100644 (file)
@@ -1,8 +1,11 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
 
 #include "MetaSession.h"
 #include "Inode.h"
 #include "Dentry.h"
 #include "Dir.h"
+#include "SnapRealm.h"
 
 ostream& operator<<(ostream &out, Inode &in)
 {
@@ -298,3 +301,195 @@ bool Inode::check_mode(uid_t ruid, gid_t rgid, gid_t *sgids, int sgids_count, ui
 
   return (mode & fmode) == fmode;
 }
+
+
+void Inode::dump(Formatter *f) const
+{
+  f->dump_stream("ino") << ino;
+  f->dump_stream("snapid") << snapid;
+  if (rdev)
+    f->dump_unsigned("rdev", rdev);
+  f->dump_stream("ctime") << ctime;
+  f->dump_stream("mode") << '0' << std::oct << mode << std::dec;
+  f->dump_unsigned("uid", uid);
+  f->dump_unsigned("gid", gid);
+  f->dump_unsigned("nlink", nlink);
+
+  f->dump_int("size", size);
+  f->dump_int("max_size", max_size);
+  f->dump_int("truncate_seq", truncate_seq);
+  f->dump_int("truncate_size", truncate_size);
+  f->dump_stream("mtime") << mtime;
+  f->dump_stream("atime") << atime;
+  f->dump_int("time_warp_seq", time_warp_seq);
+
+  f->open_object_section("layout");
+  ::dump(layout, f);
+  f->close_section();
+  if (is_dir()) {
+    f->open_object_section("dir_layout");
+    ::dump(dir_layout, f);
+    f->close_section();
+
+    /* FIXME when wip-mds-encoding is merged ***
+    f->open_object_section("dir_stat");
+    dirstat.dump(f);
+    f->close_section();
+
+    f->open_object_section("rstat");
+    rstat.dump(f);
+    f->close_section();
+    */
+  }
+
+  f->dump_unsigned("version", version);
+  f->dump_unsigned("xattr_version", xattr_version);
+  f->dump_unsigned("flags", flags);
+
+  if (is_dir()) {
+    if (!dir_contacts.empty()) {
+      f->open_object_section("dir_contants");
+      for (set<int>::iterator p = dir_contacts.begin(); p != dir_contacts.end(); ++p)
+       f->dump_int("mds", *p);
+      f->close_section();
+    }
+    f->dump_int("dir_hashed", (int)dir_hashed);
+    f->dump_int("dir_replicated", (int)dir_replicated);
+  }
+
+  f->open_array_section("caps");
+  for (map<int,Cap*>::const_iterator p = caps.begin(); p != caps.end(); ++p) {
+    f->open_object_section("cap");
+    f->dump_int("mds", p->first);
+    if (p->second == auth_cap)
+      f->dump_int("auth", 1);
+    p->second->dump(f);
+    f->close_section();
+  }
+  f->close_section();
+  if (auth_cap)
+    f->dump_int("auth_cap", auth_cap->session->mds_num);
+
+  f->dump_stream("dirty_caps") << ccap_string(dirty_caps);
+  if (flushing_caps) {
+    f->dump_stream("flushings_caps") << ccap_string(flushing_caps);
+    f->dump_unsigned("flushing_cap_seq", flushing_cap_seq);
+    f->open_object_section("flushing_cap_tid");
+    for (unsigned bit = 0; bit < CEPH_CAP_BITS; bit++) {
+      if (flushing_caps & (1 << bit)) {
+       string n(ccap_string(1 << bit));
+       f->dump_unsigned(n.c_str(), flushing_cap_tid[bit]);
+      }
+    }
+    f->close_section();
+  }
+  f->dump_int("shared_gen", shared_gen);
+  f->dump_int("cache_gen", cache_gen);
+  if (snap_caps) {
+    f->dump_int("snap_caps", snap_caps);
+    f->dump_int("snap_cap_refs", snap_cap_refs);
+  }
+  if (exporting_issued || exporting_mseq) {
+    f->dump_stream("exporting_issued") << ccap_string(exporting_issued);
+    f->dump_int("exporting_mseq", exporting_mds);
+  }
+
+  f->dump_stream("hold_caps_until") << hold_caps_until;
+  f->dump_unsigned("last_flush_tid", last_flush_tid);
+
+  if (snaprealm) {
+    f->open_object_section("snaprealm");
+    snaprealm->dump(f);
+    f->close_section();
+  }
+  if (!cap_snaps.empty()) {
+    for (map<snapid_t,CapSnap*>::const_iterator p = cap_snaps.begin(); p != cap_snaps.end(); ++p) {
+      f->open_object_section("cap_snap");
+      f->dump_stream("follows") << p->first;
+      p->second->dump(f);
+      f->close_section();
+    }
+  }
+
+  // open
+  if (!open_by_mode.empty()) {
+    f->open_array_section("open_by_mode");
+    for (map<int,int>::const_iterator p = open_by_mode.begin(); p != open_by_mode.end(); ++p) {
+      f->open_object_section("ref");
+      f->dump_unsigned("mode", p->first);
+      f->dump_unsigned("refs", p->second);
+      f->close_section();
+    }
+    f->close_section();
+  }
+  if (!cap_refs.empty()) {
+    f->open_array_section("cap_refs");
+    for (map<int,int>::const_iterator p = cap_refs.begin(); p != cap_refs.end(); ++p) {
+      f->open_object_section("cap_ref");
+      f->dump_stream("cap") << ccap_string(p->first);
+      f->dump_int("refs", p->second);
+      f->close_section();
+    }
+    f->close_section();
+  }
+
+  f->dump_unsigned("reported_size", reported_size);
+  if (wanted_max_size != max_size)
+    f->dump_unsigned("wanted_max_size", wanted_max_size);
+  if (requested_max_size != max_size)
+    f->dump_unsigned("requested_max_size", requested_max_size);
+
+  f->dump_int("ref", _ref);
+  f->dump_int("ll_ref", ll_ref);
+
+  if (!dn_set.empty()) {
+    f->open_array_section("parents");
+    for (set<Dentry*>::const_iterator p = dn_set.begin(); p != dn_set.end(); ++p) {
+      f->open_object_section("dentry");
+      f->dump_stream("dir_ino") << (*p)->dir->parent_inode->ino;
+      f->dump_string("name", (*p)->name);
+      f->close_section();
+    }
+    f->close_section();
+  }
+}
+
+void Cap::dump(Formatter *f) const
+{
+  f->dump_int("mds", session->mds_num);
+  f->dump_stream("ino") << inode->ino;
+  f->dump_unsigned("cap_id", cap_id);
+  f->dump_stream("issued") << ccap_string(issued);
+  if (implemented != issued)
+    f->dump_stream("implemented") << ccap_string(implemented);
+  f->dump_stream("wanted") << ccap_string(wanted);
+  f->dump_unsigned("seq", seq);
+  f->dump_unsigned("issue_seq", issue_seq);
+  f->dump_unsigned("mseq", mseq);
+  f->dump_unsigned("gen", gen);
+}
+
+void CapSnap::dump(Formatter *f) const
+{
+  f->dump_stream("ino") << in->ino;
+  f->dump_stream("issued") << ccap_string(issued);
+  f->dump_stream("dirty") << ccap_string(dirty);
+  f->dump_unsigned("size", size);
+  f->dump_stream("ctime") << ctime;
+  f->dump_stream("mtime") << mtime;
+  f->dump_stream("atime") << atime;
+  f->dump_int("time_warp_seq", time_warp_seq);
+  f->dump_stream("mode") << '0' << std::oct << mode << std::dec;
+  f->dump_unsigned("uid", uid);
+  f->dump_unsigned("gid", gid);
+  if (!xattrs.empty()) {
+    f->open_object_section("xattr_lens");
+    for (map<string,bufferptr>::const_iterator p = xattrs.begin(); p != xattrs.end(); ++p)
+      f->dump_int(p->first.c_str(), p->second.length());
+    f->close_section();
+  }
+  f->dump_unsigned("xattr_version", xattr_version);
+  f->dump_int("writing", (int)writing);
+  f->dump_int("dirty_data", (int)dirty_data);
+  f->dump_unsigned("flush_tid", flush_tid);
+}
index 6bda720d5a320bc97ba7d8451146c663fe5dddda..d1387a85894fa638234cff3bec6c9c01f0fd4e38 100644 (file)
@@ -1,3 +1,6 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
 #ifndef CEPH_CLIENT_INODE_H
 #define CEPH_CLIENT_INODE_H
 
@@ -31,6 +34,8 @@ struct Cap {
 
   Cap() : session(NULL), inode(NULL), cap_item(this), cap_id(0), issued(0),
               implemented(0), wanted(0), seq(0), issue_seq(0), mseq(0), gen(0) {}
+
+  void dump(Formatter *f) const;
 };
 
 struct CapSnap {
@@ -58,6 +63,8 @@ struct CapSnap {
       writing(false), dirty_data(false), flush_tid(0),
       flushing_item(this)
   {}
+
+  void dump(Formatter *f) const;
 };
 
 
@@ -241,6 +248,8 @@ class Inode {
 
   bool have_valid_size();
   Dir *open_dir();
+
+  void dump(Formatter *f) const;
 };
 
 ostream& operator<<(ostream &out, Inode &in);
diff --git a/src/client/SnapRealm.cc b/src/client/SnapRealm.cc
new file mode 100644 (file)
index 0000000..6a5918a
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "SnapRealm.h"
+#include "common/Formatter.h"
+
+void SnapRealm::dump(Formatter *f) const
+{
+  f->dump_stream("ino") << ino;
+  f->dump_int("nref", nref);
+  f->dump_stream("created") << created;
+  f->dump_stream("seq") << seq;
+  f->dump_stream("parent_ino") << parent;
+  f->dump_stream("parent_since") << parent_since;
+
+  f->open_array_section("prior_parent_snaps");
+  for (vector<snapid_t>::const_iterator p = prior_parent_snaps.begin(); p != prior_parent_snaps.end(); ++p)
+    f->dump_stream("snapid") << *p;
+  f->close_section();
+  f->open_array_section("my_snaps");
+  for (vector<snapid_t>::const_iterator p = my_snaps.begin(); p != my_snaps.end(); ++p)
+    f->dump_stream("snapid") << *p;
+  f->close_section();
+
+  f->open_array_section("children");
+  for (set<SnapRealm*>::const_iterator p = pchildren.begin(); p != pchildren.end(); ++p)
+    f->dump_stream("child") << (*p)->ino;
+  f->close_section();
+}
index 839c68aef696a77e848407f71dbc0721fd910e0e..34d895683007685d2708fefaba6ec85ba2f754dc 100644 (file)
@@ -1,6 +1,13 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
 #ifndef CEPH_CLIENT_SNAPREALM_H
 #define CEPH_CLIENT_SNAPREALM_H
 
+#include "include/types.h"
+#include "common/snap_types.h"
+#include "include/xlist.h"
+
 class Inode;
 
 struct SnapRealm {
@@ -38,6 +45,8 @@ public:
       build_snap_context();
     return cached_snap_context;
   }
+
+  void dump(Formatter *f) const;
 };
 
 inline ostream& operator<<(ostream& out, const SnapRealm& r) {