diff --git a/doc/man/8/ceph-dencoder.rst b/doc/man/8/ceph-dencoder.rst index dcebe50f782..a7252a987a3 100644 --- a/doc/man/8/ceph-dencoder.rst +++ b/doc/man/8/ceph-dencoder.rst @@ -45,6 +45,11 @@ Commands Select the given type for future ``encode`` or ``decode`` operations. +.. option:: skip + + Seek into the imported file before reading data structure, use + this with objects that have a preamble/header before the object of interest. + .. option:: decode Decode the contents of the in-memory buffer into an instance of the @@ -84,7 +89,9 @@ Commands Example ======= -Say you want to examine an attribute on an object stored by ``ceph-osd``. You can do:: +Say you want to examine an attribute on an object stored by ``ceph-osd``. You can do this: + +:: $ cd /mnt/osd.12/current/2.b_head $ attr -l foo_bar_head_EFE6384B @@ -113,6 +120,21 @@ Say you want to examine an attribute on an object stored by ``ceph-osd``. You c "truncate_size": 0, "watchers": {}} +Alternatively, perhaps you wish to dump an internal CephFS metadata object, you might +do that like this: + +:: + + $ rados -p metadata get mds_snaptable mds_snaptable.bin + $ ceph-dencoder type SnapServer skip 8 import mds_snaptable.bin decode dump_json + { "snapserver": { "last_snap": 1, + "pending_noop": [], + "snaps": [], + "need_to_purge": {}, + "pending_create": [], + "pending_destroy": []}} + + Availability ============ diff --git a/src/mds/AnchorServer.h b/src/mds/AnchorServer.h index fb38051bb7a..d6f1d840cd7 100644 --- a/src/mds/AnchorServer.h +++ b/src/mds/AnchorServer.h @@ -33,7 +33,7 @@ class AnchorServer : public MDSTableServer { map > > pending_ops; void reset_state(); - void encode_server_state(bufferlist& bl) { + void encode_server_state(bufferlist& bl) const { ENCODE_START(2, 2, bl); ::encode(anchor_map, bl); ::encode(pending_create, bl); @@ -70,10 +70,11 @@ class AnchorServer : public MDSTableServer { // for the dencoder AnchorServer() : MDSTableServer(NULL, TABLE_ANCHOR) {} void encode(bufferlist& bl) const { - AnchorServer *me = const_cast(this); - me->encode_server_state(bl); + encode_server_state(bl); + } + void decode(bufferlist::iterator& bl) { + decode_server_state(bl); } - void decode(bufferlist::iterator& bl) { decode_server_state(bl); } // server bits void _prepare(bufferlist &bl, uint64_t reqid, int bymds); diff --git a/src/mds/InoTable.cc b/src/mds/InoTable.cc index 426b9150ea6..f0bf3bd576c 100644 --- a/src/mds/InoTable.cc +++ b/src/mds/InoTable.cc @@ -156,3 +156,34 @@ void InoTable::skip_inos(inodeno_t i) projected_version = ++version; dout(10) << "skip_inos now " << free << dendl; } + +void InoTable::dump(Formatter *f) const +{ + f->open_object_section("inotable"); + + f->open_array_section("projected_free"); + for (interval_set::const_iterator i = projected_free.begin(); i != projected_free.end(); ++i) { + f->open_object_section("range"); + f->dump_int("start", (*i).first); + f->dump_int("len", (*i).second); + f->close_section(); + } + f->close_section(); + + f->open_array_section("free"); + for (interval_set::const_iterator i = free.begin(); i != free.end(); ++i) { + f->open_object_section("range"); + f->dump_int("start", (*i).first); + f->dump_int("len", (*i).second); + f->close_section(); + } + f->close_section(); + + f->close_section(); +} + + +void InoTable::generate_test_instances(list& ls) +{ + ls.push_back(new InoTable()); +} diff --git a/src/mds/InoTable.h b/src/mds/InoTable.h index 88fd9ecaaaa..100db956409 100644 --- a/src/mds/InoTable.h +++ b/src/mds/InoTable.h @@ -43,7 +43,7 @@ class InoTable : public MDSTable { void replay_reset(); void reset_state(); - void encode_state(bufferlist& bl) { + void encode_state(bufferlist& bl) const { ENCODE_START(2, 2, bl); ::encode(free, bl); ENCODE_FINISH(bl); @@ -55,6 +55,17 @@ class InoTable : public MDSTable { DECODE_FINISH(bl); } + // To permit enc/decoding in isolation in dencoder + InoTable() : MDSTable(NULL, "inotable", true) {} + void encode(bufferlist& bl) const { + encode_state(bl); + } + void decode(bufferlist::iterator& bl) { + decode_state(bl); + } + void dump(Formatter *f) const; + static void generate_test_instances(list& ls); + void skip_inos(inodeno_t i); }; diff --git a/src/mds/MDSTable.cc b/src/mds/MDSTable.cc index ef0326dfbd3..3f544b7d065 100644 --- a/src/mds/MDSTable.cc +++ b/src/mds/MDSTable.cc @@ -27,7 +27,7 @@ #define dout_subsys ceph_subsys_mds #undef dout_prefix -#define dout_prefix *_dout << "mds." << mds->get_nodeid() << "." << table_name << ": " +#define dout_prefix *_dout << "mds." << (mds ? mds->get_nodeid() : -1) << "." << table_name << ": " class C_MT_Save : public Context { diff --git a/src/mds/MDSTable.h b/src/mds/MDSTable.h index f258cf9d5bf..edcb203201b 100644 --- a/src/mds/MDSTable.h +++ b/src/mds/MDSTable.h @@ -79,7 +79,7 @@ public: // child must overload these virtual void reset_state() = 0; virtual void decode_state(bufferlist::iterator& p) = 0; - virtual void encode_state(bufferlist& bl) = 0; + virtual void encode_state(bufferlist& bl) const = 0; }; #endif diff --git a/src/mds/MDSTableServer.h b/src/mds/MDSTableServer.h index 55827e7c0b9..223fc91f0ac 100644 --- a/src/mds/MDSTableServer.h +++ b/src/mds/MDSTableServer.h @@ -77,10 +77,10 @@ private: void handle_request(MMDSTableRequest *m); void do_server_update(bufferlist& bl); - virtual void encode_server_state(bufferlist& bl) = 0; + virtual void encode_server_state(bufferlist& bl) const = 0; virtual void decode_server_state(bufferlist::iterator& bl) = 0; - void encode_state(bufferlist& bl) { + void encode_state(bufferlist& bl) const { encode_server_state(bl); ::encode(pending_for_mds, bl); } diff --git a/src/mds/SnapServer.cc b/src/mds/SnapServer.cc index f8aedb668bf..3d2b4176cd1 100644 --- a/src/mds/SnapServer.cc +++ b/src/mds/SnapServer.cc @@ -257,3 +257,84 @@ void SnapServer::check_osd_map(bool force) last_checked_osdmap = version; } + + +void SnapServer::dump(Formatter *f) const +{ + f->open_object_section("snapserver"); + + f->dump_int("last_snap", last_snap.val); + + f->open_array_section("pending_noop"); + for(set::const_iterator i = pending_noop.begin(); i != pending_noop.end(); ++i) { + f->dump_unsigned("version", *i); + } + f->close_section(); + + f->open_array_section("snaps"); + for (map::const_iterator i = snaps.begin(); i != snaps.end(); ++i) { + f->open_object_section("snap"); + i->second.dump(f); + f->close_section(); + } + f->close_section(); + + f->open_object_section("need_to_purge"); + for (map >::const_iterator i = need_to_purge.begin(); i != need_to_purge.end(); ++i) { + stringstream pool_id; + pool_id << i->first; + f->open_array_section(pool_id.str().c_str()); + for (set::const_iterator s = i->second.begin(); s != i->second.end(); ++s) { + f->dump_unsigned("snapid", s->val); + } + f->close_section(); + } + f->close_section(); + + f->open_array_section("pending_create"); + for(map::const_iterator i = pending_create.begin(); i != pending_create.end(); ++i) { + f->open_object_section("snap"); + f->dump_unsigned("version", i->first); + f->open_object_section("snapinfo"); + i->second.dump(f); + f->close_section(); + f->close_section(); + } + f->close_section(); + + f->open_array_section("pending_destroy"); + for(map >::const_iterator i = pending_destroy.begin(); i != pending_destroy.end(); ++i) { + f->open_object_section("snap"); + f->dump_unsigned("version", i->first); + f->dump_unsigned("removed_snap", i->second.first); + f->dump_unsigned("seq", i->second.second); + f->close_section(); + } + f->close_section(); + + f->close_section(); +} + +void SnapServer::generate_test_instances(list& ls) +{ + list snapinfo_instances; + SnapInfo::generate_test_instances(snapinfo_instances); + SnapInfo populated_snapinfo = *(snapinfo_instances.back()); + for (list::iterator i = snapinfo_instances.begin(); i != snapinfo_instances.end(); ++i) { + delete *i; + } + + SnapServer *blank = new SnapServer(); + ls.push_back(blank); + SnapServer *populated = new SnapServer(); + populated->last_snap = 123; + populated->snaps[456] = populated_snapinfo; + populated->need_to_purge[2].insert(012); + populated->pending_create[234] = populated_snapinfo; + populated->pending_destroy[345].first = 567; + populated->pending_destroy[345].second = 768; + populated->pending_noop.insert(890); + + ls.push_back(populated); + +} diff --git a/src/mds/SnapServer.h b/src/mds/SnapServer.h index a3c3bd7d7f0..95e15080df0 100644 --- a/src/mds/SnapServer.h +++ b/src/mds/SnapServer.h @@ -39,7 +39,7 @@ public: last_checked_osdmap(0) { } void reset_state(); - void encode_server_state(bufferlist& bl) { + void encode_server_state(bufferlist& bl) const { ENCODE_START(3, 3, bl); ::encode(last_snap, bl); ::encode(snaps, bl); @@ -67,6 +67,17 @@ public: DECODE_FINISH(bl); } + // To permit enc/decoding in isolation in dencoder + SnapServer() : MDSTableServer(NULL, TABLE_SNAP), last_checked_osdmap(0) {} + void encode(bufferlist& bl) const { + encode_server_state(bl); + } + void decode(bufferlist::iterator& bl) { + decode_server_state(bl); + } + void dump(Formatter *f) const; + static void generate_test_instances(list& ls); + // server bits void _prepare(bufferlist &bl, uint64_t reqid, int bymds); bool _is_prepared(version_t tid); diff --git a/src/osdc/Journaler.h b/src/osdc/Journaler.h index 51241c197e8..e3a57135b32 100644 --- a/src/osdc/Journaler.h +++ b/src/osdc/Journaler.h @@ -98,6 +98,38 @@ public: ::decode(write_pos, bl); ::decode(layout, bl); } + + void dump(Formatter *f) const { + f->open_object_section("journal_header"); + { + f->dump_string("magic", magic); + f->dump_unsigned("write_pos", write_pos); + f->dump_unsigned("expire_pos", expire_pos); + f->dump_unsigned("trimmed_pos", trimmed_pos); + f->open_object_section("layout"); + { + f->dump_unsigned("stripe_unit", layout.fl_stripe_unit); + f->dump_unsigned("stripe_count", layout.fl_stripe_unit); + f->dump_unsigned("object_size", layout.fl_stripe_unit); + f->dump_unsigned("cas_hash", layout.fl_stripe_unit); + f->dump_unsigned("object_stripe_unit", layout.fl_stripe_unit); + f->dump_unsigned("pg_pool", layout.fl_stripe_unit); + } + f->close_section(); // layout + } + f->close_section(); // journal_header + } + + static void generate_test_instances(list &ls) + { + ls.push_back(new Header()); + ls.push_back(new Header()); + ls.back()->trimmed_pos = 1; + ls.back()->expire_pos = 2; + ls.back()->unused_field = 3; + ls.back()->write_pos = 4; + ls.back()->magic = "magique"; + } } last_written, last_committed; WRITE_CLASS_ENCODER(Header) diff --git a/src/test/encoding/ceph_dencoder.cc b/src/test/encoding/ceph_dencoder.cc index bb69fddab26..8391f33cb2f 100644 --- a/src/test/encoding/ceph_dencoder.cc +++ b/src/test/encoding/ceph_dencoder.cc @@ -47,7 +47,7 @@ void usage(ostream &out) } struct Dencoder { virtual ~Dencoder() {} - virtual string decode(bufferlist bl) = 0; + virtual string decode(bufferlist bl, uint64_t seek) = 0; virtual void encode(bufferlist& out, uint64_t features) = 0; virtual void dump(ceph::Formatter *f) = 0; virtual void copy() { @@ -75,8 +75,9 @@ public: delete m_object; } - string decode(bufferlist bl) { + string decode(bufferlist bl, uint64_t seek) { bufferlist::iterator p = bl.begin(); + p.seek(seek); try { m_object->decode(p); } @@ -168,8 +169,9 @@ public: m_object->put(); } - string decode(bufferlist bl) { + string decode(bufferlist bl, uint64_t seek) { bufferlist::iterator p = bl.begin(); + p.seek(seek); try { Message *n = decode_message(g_ceph_context, p); if (!n) @@ -253,6 +255,7 @@ int main(int argc, const char **argv) Dencoder *den = NULL; uint64_t features = CEPH_FEATURES_SUPPORTED_DEFAULT; bufferlist encbl; + uint64_t skip = 0; if (args.empty()) { usage(cerr); @@ -285,6 +288,13 @@ int main(int argc, const char **argv) } den = dencoders[cname]; den->generate(); + } else if (*i == string("skip")) { + ++i; + if (i == args.end()) { + usage(cerr); + exit(1); + } + skip = atoi(*i); } else if (*i == string("get_features")) { cout << CEPH_FEATURES_SUPPORTED_DEFAULT << std::endl; exit(0); @@ -309,7 +319,7 @@ int main(int argc, const char **argv) usage(cerr); exit(1); } - err = den->decode(encbl); + err = den->decode(encbl, skip); } else if (*i == string("copy_ctor")) { if (!den) { cerr << "must first select type with 'type '" << std::endl; @@ -348,6 +358,7 @@ int main(int argc, const char **argv) cerr << "error reading " << *i << ": " << err << std::endl; exit(1); } + } else if (*i == string("export")) { ++i; if (i == args.end()) { diff --git a/src/test/encoding/types.h b/src/test/encoding/types.h index 678bb627869..7df2b6c1134 100644 --- a/src/test/encoding/types.h +++ b/src/test/encoding/types.h @@ -129,6 +129,9 @@ TYPE(MonCap) TYPE(DBObjectMap::_Header) TYPE(DBObjectMap::State) +#include "osdc/Journaler.h" +TYPE(Journaler::Header) + #include "mds/Anchor.h" TYPE(Anchor) @@ -164,7 +167,13 @@ TYPE_FEATUREFUL(MDSMap::mds_info_t) TYPE_NOCOPY(Capability) #include "mds/AnchorServer.h" -TYPE(AnchorServer) +TYPEWITHSTRAYDATA(AnchorServer) + +#include "mds/InoTable.h" +TYPE(InoTable) + +#include "mds/SnapServer.h" +TYPEWITHSTRAYDATA(SnapServer) #include "mds/SessionMap.h" TYPE(SessionMap)