mirror of
https://github.com/ceph/ceph
synced 2025-01-01 16:42:29 +00:00
mds: Add encode/decode/dump for use with dencoder
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>
This commit is contained in:
parent
c5c7f6c8e8
commit
541beb87dc
@ -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
|
||||
============
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user