From: Sage Weil Date: Mon, 12 Nov 2012 19:06:42 +0000 (-0800) Subject: client: add dump_cache asok command X-Git-Tag: v0.55~118^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fc6b82f01dded9089e12f993a423633b3eefa2c7;p=ceph.git client: add dump_cache asok command Signed-off-by: Sage Weil --- diff --git a/src/Makefile.am b/src/Makefile.am index e599d7c16db6..2acfd05b684d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/client/Client.cc b/src/client/Client.cc index 0dbc489209f8..6a6d656196f0 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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& did, bool disconnected) +void Client::dump_inode(Formatter *f, Inode *in, set& did, bool disconnected) { filepath path; in->make_long_path(path); @@ -268,6 +270,16 @@ void Client::dump_inode(Inode *in, set& 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& 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 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::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); diff --git a/src/client/Client.h b/src/client/Client.h index d261388c8334..840124d741b2 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -370,8 +370,8 @@ protected: void trim_dentry(Dentry *dn); void trim_caps(int mds, int max); - void dump_inode(Inode *in, set& did, bool disconnected); - void dump_cache(); // debug + void dump_inode(Formatter *f, Inode *in, set& 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 index 000000000000..8bb21ace2e38 --- /dev/null +++ b/src/client/Dentry.cc @@ -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); +} diff --git a/src/client/Dentry.h b/src/client/Dentry.h index 701a0f778575..932f17dbafca 100644 --- a/src/client/Dentry.h +++ b/src/client/Dentry.h @@ -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: diff --git a/src/client/Inode.cc b/src/client/Inode.cc index 3d669d6ec42e..0dfd1ebdce80 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -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::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::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::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::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::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::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::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); +} diff --git a/src/client/Inode.h b/src/client/Inode.h index 6bda720d5a32..d1387a85894f 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -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 index 000000000000..6a5918a05891 --- /dev/null +++ b/src/client/SnapRealm.cc @@ -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::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::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::const_iterator p = pchildren.begin(); p != pchildren.end(); ++p) + f->dump_stream("child") << (*p)->ino; + f->close_section(); +} diff --git a/src/client/SnapRealm.h b/src/client/SnapRealm.h index 839c68aef696..34d895683007 100644 --- a/src/client/SnapRealm.h +++ b/src/client/SnapRealm.h @@ -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) {