]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: Add encode/decode/dump for use with dencoder 1264/head
authorJohn Spray <john.spray@inktank.com>
Wed, 5 Feb 2014 23:17:29 +0000 (23:17 +0000)
committerJohn Spray <john.spray@inktank.com>
Thu, 20 Feb 2014 15:22:29 +0000 (15:22 +0000)
This is for the MDSTable subclasses: AnchorServer,
SnapServer, InoTable.  AnchorServer was partially there
but didn't work in practice dumped objects because of
the version prefix on the object.

This adds a skip argument to ceph-dencoder for getting
past fixed size prefixes.  The encode_server_state method
is also made const to avoid the need for const_casting (and
because it really is const)

Signed-off-by: John Spray <john.spray@inktank.com>
12 files changed:
doc/man/8/ceph-dencoder.rst
src/mds/AnchorServer.h
src/mds/InoTable.cc
src/mds/InoTable.h
src/mds/MDSTable.cc
src/mds/MDSTable.h
src/mds/MDSTableServer.h
src/mds/SnapServer.cc
src/mds/SnapServer.h
src/osdc/Journaler.h
src/test/encoding/ceph_dencoder.cc
src/test/encoding/types.h

index dcebe50f78214e84b58550782f85de985a331673..a7252a987a3a9dbf2d4242042f0dd8cd85c46c03 100644 (file)
@@ -45,6 +45,11 @@ Commands
 
    Select the given type for future ``encode`` or ``decode`` operations.
 
+.. option:: skip <bytes>
+
+   Seek <bytes> 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
 ============
 
index fb38051bb7a27979e70f724b410c498eff72a508..d6f1d840cd7c46db99859868fa42b6c9ff6ed2fe 100644 (file)
@@ -33,7 +33,7 @@ class AnchorServer : public MDSTableServer {
   map<inodeno_t, list<pair<version_t, Context*> > > 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<AnchorServer*>(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);
index 426b9150ea60d44541d5d5eb703fcd7da2e00d90..f0bf3bd576c5b1d91ea8cb6d7d609ca274e73857 100644 (file)
@@ -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<inodeno_t>::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<inodeno_t>::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<InoTable*>& ls)
+{
+  ls.push_back(new InoTable());
+}
index 88fd9ecaaaa0b0fb545eecc2d5de7e9a404b1c2a..100db95640902079eff8bb7297bff9ed584d902e 100644 (file)
@@ -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<InoTable*>& ls);
+
   void skip_inos(inodeno_t i);
 };
 
index ef0326dfbd379c944313bcf134b88244efe3efe0..3f544b7d06558a8b02bf2f5d0d2ebc2df3572e95 100644 (file)
@@ -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 {
index f258cf9d5bf0b656c7f22d3b3bb262443d43c146..edcb203201be5ec251ed781186c503545e9ae835 100644 (file)
@@ -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
index 55827e7c0b97adb42f020901cec707fab37406ff..223fc91f0acefb8605bc851cf2789134adc293ad 100644 (file)
@@ -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);
   }
index f8aedb668bff2604b9ddd56798dac3cba7ab4f17..3d2b4176cd11c04b5842c9b3606c0a9c352194e8 100644 (file)
@@ -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<version_t>::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<snapid_t, SnapInfo>::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<int, set<snapid_t> >::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<snapid_t>::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<version_t, SnapInfo>::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<version_t, pair<snapid_t, snapid_t> >::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<SnapServer*>& ls)
+{
+  list<SnapInfo*> snapinfo_instances;
+  SnapInfo::generate_test_instances(snapinfo_instances);
+  SnapInfo populated_snapinfo = *(snapinfo_instances.back());
+  for (list<SnapInfo*>::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);
+
+}
index a3c3bd7d7f0e30976f347773de1f8de89324e66b..95e15080df00cdcef2bff254d5786c1e95e1ba40 100644 (file)
@@ -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<SnapServer*>& ls);
+
   // server bits
   void _prepare(bufferlist &bl, uint64_t reqid, int bymds);
   bool _is_prepared(version_t tid);
index 51241c197e87c244c3d375893acee86f654971de..e3a57135b322ecfbbe07aef7a346f34f0725905a 100644 (file)
@@ -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<Header*> &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)
 
index bb69fddab26e8c2a27e6d160bb61a262ef55ebd3..8391f33cb2fab4e7e3c427531e9ba5cc7b5e28a1 100644 (file)
@@ -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 <name>'" << 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()) {
index 678bb62786931204f13e35f1bcffe7bf7adc0c38..7df2b6c1134ced35926d9e91badd4b35bb689a2a 100644 (file)
@@ -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)