// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #include #include #include #include #include "include/types.h" #include "common/Formatter.h" #include "common/ceph_argparse.h" #include "common/errno.h" #include "osdc/Journaler.h" #include "mds/mdstypes.h" #include "mds/LogEvent.h" #include "mds/InoTable.h" #include "mds/CDentry.h" #include "mds/events/ENoOp.h" #include "mds/events/EUpdate.h" #include "mds/JournalPointer.h" // #include "JournalScanner.h" // #include "EventOutput.h" // #include "Dumper.h" // #include "Resetter.h" // #include "JournalTool.h" #include "MetaTool.h" #include "type_helper.hpp" #include "include/object.h" WRITE_RAW_ENCODER(char) WRITE_RAW_ENCODER(unsigned char) #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mds #undef dout_prefix #define dout_prefix *_dout << __func__ << ": " void MetaTool::meta_op::release() { for (const auto& i : inodes) { delete i.second; } while (!sub_ops.empty()) { delete sub_ops.top(); sub_ops.pop(); } } void MetaTool::inode_meta_t::decode_json(JSONObj *obj) { unsigned long long tmp; JSONDecoder::decode_json("snapid_t", tmp, obj, true); _f.val = tmp; JSONDecoder::decode_json("itype", tmp, obj, true); _t = tmp; if (NULL == _i) _i = new InodeStore; JSONDecoder::decode_json("store", *_i, obj, true); } void MetaTool::usage() { generic_client_usage(); } int MetaTool::main(string& mode, string& rank_str, string& minfo, string&ino, string& out, string& in, bool confirm ) { int r = 0; std::string manual_meta_pool; std::string manual_data_pool; std::string manual_rank_num; bool manual_mode = false; if (minfo != "") { vector v; string_split(minfo, v); manual_meta_pool = v.size() >= 1 ? v[0] : ""; manual_data_pool = v.size() >= 2 ? v[1] : ""; manual_rank_num = v.size() >= 3 ? v[2] : ""; std::cout << "("<< minfo<< ")=>" << " mpool: " << manual_meta_pool << " dpool: " << manual_data_pool << " rank: " << manual_rank_num << std::endl; if (!manual_meta_pool.empty() && !manual_data_pool.empty() && !manual_rank_num.empty()) { std::cout << "you specify rank: " << manual_rank_num << " mpool: " << manual_meta_pool << " dpool: " << manual_data_pool << "\nstart manual mode!!"<< std::endl; manual_mode = true; } } // RADOS init r = rados.init_with_context(g_ceph_context); if (r < 0) { cerr << "RADOS unavailable" << std::endl; return r; } if (_debug) cout << "MetaTool: connecting to RADOS..." << std::endl; r = rados.connect(); if (r < 0) { cerr << "couldn't connect to cluster: " << cpp_strerror(r) << std::endl; return r; } if (!manual_mode) { r = role_selector.parse(*fsmap, rank_str); if (r != 0) { cerr << "Couldn't determine MDS rank." << std::endl; return r; } auto fs = fsmap->get_filesystem(role_selector.get_ns()); assert(fs != nullptr); // prepare io for meta pool int64_t const pool_id = fs->mds_map.get_metadata_pool(); features = fs->mds_map.get_up_features(); if (features == 0) features = CEPH_FEATURES_SUPPORTED_DEFAULT; else if (features != CEPH_FEATURES_SUPPORTED_DEFAULT) { cout << "I think we need to check the feature! : " << features << std::endl; return -1; } std::string pool_name; r = rados.pool_reverse_lookup(pool_id, &pool_name); if (r < 0) { cerr << "Pool " << pool_id << " named in MDS map not found in RADOS!" << std::endl; return r; } if (_debug) cout << "MetaTool: creating IoCtx.." << std::endl; r = rados.ioctx_create(pool_name.c_str(), io_meta); assert(r == 0); output.dup(io_meta); // prepare io for data pool for (const auto p : fs->mds_map.get_data_pools()) { r = rados.pool_reverse_lookup(p, &pool_name); if (r < 0) { cerr << "Pool " << pool_id << " named in MDS map not found in RADOS!" << std::endl; return r; } librados::IoCtx* io_data = new librados::IoCtx; r = rados.ioctx_create(pool_name.c_str(), *io_data); assert(r == 0); io_data_v.push_back(io_data); } for (auto role : role_selector.get_roles()) { rank = role.rank; r = process(mode, ino, out, in, confirm); cout << "executing for rank " << rank << " op[" <(manual_rank_num); r = process(mode, ino, out, in, confirm); cout << "op[" << mode << "] ret : " << r << std::endl; } return r; } int MetaTool::process(string& mode, string& ino, string out, string in, bool confirm) { if (mode == "showm") { return show_meta_info(ino, out); } else if (mode == "showfn") { return show_fnode(ino, out); } else if (mode == "listc") { return list_meta_info(ino, out); } else if (mode == "amend") { return amend_meta_info(ino, in, confirm); } else if (mode == "amendfn") { return amend_fnode(in, confirm); } else { cerr << "bad command '" << mode << "'" << std::endl; return -EINVAL; } } int MetaTool::show_fnode(string& ino, string& out) { if (ino != "0") { inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0); meta_op op(_debug, out); meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_SHOW_FN; nsop->sub_ino_t = meta_op::INO_DIR; nsop->ino = i_ino; op.push_op(nsop); return op_process(op); } else { cerr << "parameter error? : ino = " << ino << std::endl; } return 0; } int MetaTool::amend_fnode(string& in, bool confirm) { meta_op op(_debug, "", in, confirm); meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_AMEND_FN; nsop->sub_ino_t = meta_op::INO_DIR; nsop->ino = 0; op.push_op(nsop); return op_process(op); } int MetaTool::amend_meta_info(string& ino, string& in, bool confirm) { if (ino != "0" && in != "") { inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0); meta_op op(_debug, "", in, confirm); meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_AMEND; nsop->sub_ino_t = meta_op::INO_DIR; nsop->ino = i_ino; op.push_op(nsop); return op_process(op); } else { cerr << "parameter error? : ino = " << ino << std::endl; } return 0; } int MetaTool::list_meta_info(string& ino, string& out) { if (ino != "0") { inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0); meta_op op(_debug, out); meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; nsop->ino = i_ino; op.push_op(nsop); return op_process(op); } else { cerr << "parameter error? : ino = " << ino << std::endl; } return 0; } int MetaTool::show_meta_info(string& ino, string& out) { if (ino != "0") { inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0); meta_op op(_debug, out); meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_SHOW; nsop->sub_ino_t = meta_op::INO_DIR; nsop->ino = i_ino; op.push_op(nsop); return op_process(op); } else { cerr << "parameter error? : ino = " << ino << std::endl; } return 0; } int MetaTool::op_process(meta_op& op) { int r = 0; while (!op.no_sops()) { if (_debug) std::cout << "process : " << op.top_op()->detail() << std::endl; switch(op.top_op()->sub_op_t) { case meta_op::OP_LIST: r = list_meta(op); break; case meta_op::OP_LTRACE: r = file_meta(op); break; case meta_op::OP_SHOW: r = show_meta(op); break; case meta_op::OP_AMEND: r = amend_meta(op); break; case meta_op::OP_SHOW_FN: r = show_fn(op); break; case meta_op::OP_AMEND_FN: r = amend_fn(op); break; default: cerr << "unknow op" << std::endl; } if (r == 0) op.pop_op(); else if (r < 0) op.clear_sops(); } op.release(); return r; } int MetaTool::amend_meta(meta_op &op) { meta_op::sub_op* sop = op.top_op(); auto item = op.inodes.find(sop->ino); auto item_k = op.okeys.find(sop->ino); if (item != op.inodes.end() && item_k != op.okeys.end()) { if (_amend_meta(item_k->second, *(item->second), op.infile(), op) < 0) return -1; } else { if (op.inodes.empty()) { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; nsop->trace_level = 0; nsop->ino_c = sop->ino; op.push_op(nsop); return 1; } else { return -1; } } return 0; } void MetaTool::inode_meta_t::encode(::ceph::bufferlist& bl, uint64_t features) { ::encode(_f, bl); ::encode(_t, bl); _i->encode_bare(bl, features); } int MetaTool::_amend_meta(string& k, inode_meta_t& inode_meta, const string& fn, meta_op& op) { JSONParser parser; if (!parser.parse(fn.c_str())) { cout << "Error parsing create user response" << std::endl; return -1; } try { inode_meta.decode_json(&parser); } catch (JSONDecoder::err& e) { cout << "failed to decode JSON input: " << e.what() << std::endl; return -1; } if (!op.confirm_chg() || op.is_debug()) { cout << "you will amend info of inode ==>: " << std::endl; _show_meta(inode_meta, ""); } if (!op.confirm_chg()) { cout << "warning: this operation is irreversibl!!!\n" << " You must confirm that all logs of mds have been flushed!!!\n" << " if you want amend it, please add --yes-i-really-really-mean-it!!!" << std::endl; return -1; } bufferlist bl; inode_meta.encode(bl, features); map to_set; to_set[k].swap(bl); inode_backpointer_t bp; if (!op.top_op()->get_ancestor(bp)) return -1; frag_t frag; auto item = op.inodes.find(bp.dirino); if (item != op.inodes.end()) { frag = item->second->get_meta()->pick_dirfrag(bp.dname); } string oid = obj_name(bp.dirino, frag); int ret = io_meta.omap_set(oid, to_set); to_set.clear(); return ret; } int MetaTool::show_fn(meta_op &op) { meta_op::sub_op* sop = op.top_op(); auto item = op.inodes.find(sop->ino); if (item != op.inodes.end()) { if (_show_fn(*(item->second), op.outfile()) < 0) return -1; } else { if (op.inodes.empty()) { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; nsop->trace_level = 0; nsop->ino_c = sop->ino; op.push_op(nsop); return 1; } else return -1; } return 0; } int MetaTool::_show_fn(inode_meta_t& inode_meta, const string& fn) { std::list frags; inode_meta.get_meta()->dirfragtree.get_leaves(frags); std::stringstream ds; std::string format = "json"; std::string oids; Formatter* f = Formatter::create(format); f->enable_line_break(); f->open_object_section("fnodes"); for (const auto &frag : frags) { bufferlist hbl; string oid = obj_name(inode_meta.get_meta()->inode->ino, frag); int ret = io_meta.omap_get_header(oid, &hbl); if (ret < 0) { std::cerr << __func__ << " : can't find oid("<< oid << ")" << std::endl; return -1; } { fnode_t got_fnode; try { auto p = hbl.cbegin(); ::decode(got_fnode, p); } catch (const buffer::error &err) { cerr << "corrupt fnode header in " << oid << ": " << err.what() << std::endl; return -1; } if (!oids.empty()) oids += ","; oids += oid; f->open_object_section(oid.c_str()); got_fnode.dump(f); f->close_section(); } } f->dump_string("oids", oids.c_str()); f->close_section(); f->flush(ds); if (fn != "") { ofstream o; o.open(fn); if (o) { o << ds.str(); o.close(); } else { cout << "out to file (" << fn << ") failed" << std::endl; cout << ds.str() << std::endl; } } else std::cout << ds.str() << std::endl; return 0; } int MetaTool::amend_fn(meta_op &op) { if (_amend_fn(op.infile(), op.confirm_chg()) < 0) return -1; return 0; } int MetaTool::_amend_fn(const string& fn, bool confirm) { JSONParser parser; if (!parser.parse(fn.c_str())) { cout << "Error parsing create user response : " << fn << std::endl; return -1; } if (!confirm) { cout << "warning: this operation is irreversibl!!!\n" << " You must confirm that all logs of mds have been flushed!!!\n" << " if you want amend it, please add --yes-i-really-really-mean-it!!!" << std::endl; return -1; } try { string tmp; JSONDecoder::decode_json("oids", tmp, &parser, true); string::size_type pos1, pos2; vector v; string c = ","; pos2 = tmp.find(c); pos1 = 0; while (string::npos != pos2) { v.push_back(tmp.substr(pos1, pos2-pos1)); pos1 = pos2 + c.size(); pos2 = tmp.find(c, pos1); } if (pos1 != tmp.length()) v.push_back(tmp.substr(pos1)); int ret = 0; for (auto i : v) { cout << "amend frag : " << i << "..." << std::endl; fnode_t fnode; JSONDecoder::decode_json(i.c_str(), fnode, &parser, true); bufferlist bl; fnode.encode(bl); ret = io_meta.omap_set_header(i, bl); if (ret < 0) return ret; } } catch (JSONDecoder::err& e) { cout << "failed to decode JSON input: " << e.what() << std::endl; return -1; } return 0; } int MetaTool::show_meta(meta_op &op) { meta_op::sub_op* sop = op.top_op(); auto item = op.inodes.find(sop->ino); if (item != op.inodes.end()) { if (_show_meta(*(item->second), op.outfile()) < 0) return -1; } else { if (op.inodes.empty()) { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; nsop->trace_level = 0; nsop->ino_c = sop->ino; op.push_op(nsop); return 1; } else { return -1; } } return 0; } int MetaTool::_show_meta(inode_meta_t& inode_meta, const string& fn) { std::stringstream ds; std::string format = "json"; InodeStore& inode_data = *inode_meta.get_meta(); Formatter* f = Formatter::create(format); f->enable_line_break(); f->open_object_section("meta"); f->dump_unsigned("snapid_t", inode_meta.get_snapid()); f->dump_unsigned("itype", inode_meta.get_type()); f->open_object_section("store"); inode_data.dump(f); try { if (inode_data.snap_blob.length()) { sr_t srnode; auto p = inode_data.snap_blob.cbegin(); decode(srnode, p); f->open_object_section("snap_blob"); srnode.dump(f); f->close_section(); } } catch (const buffer::error &err) { cerr << "corrupt decode in snap_blob" << ": " << err.what() << std::endl; return -1; } f->close_section(); f->close_section(); f->flush(ds); if (fn != "") { ofstream o; o.open(fn); if (o) { o << ds.str(); o.close(); } else { cout << "out to file (" << fn << ") failed" << std::endl; cout << ds.str() << std::endl; } } else std::cout << ds.str() << std::endl; return 0; } int MetaTool::list_meta(meta_op &op) { meta_op::sub_op* sop = op.top_op(); bool list_all = false; string oid; inodeno_t ino = sop->ino_c; frag_t frag = sop->frag; if (sop->ino_c == 0) { list_all = true; oid = obj_name(sop->ino, frag); } else { if (_debug) std::cout << __func__ << " : " << sop->trace_level << " " << op.ancestors.size() << std::endl; inode_backpointer_t bp; if (sop->get_c_ancestor(bp)) { auto item = op.inodes.find(bp.dirino); if (item != op.inodes.end()) { frag = item->second->get_meta()->pick_dirfrag(bp.dname); } oid = obj_name(bp.dirino, frag); } else { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->ino = sop->ino_c; nsop->sub_op_t = meta_op::OP_LTRACE; nsop->sub_ino_t = meta_op::INO_DIR; op.push_op(nsop); return 1; } } if (_debug) std::cout << __func__ << " : " << string(list_all?"listall ":"info ") << oid << " "<< ino << std::endl; bufferlist hbl; int ret = io_meta.omap_get_header(oid, &hbl); if (ret < 0) { std::cerr << __func__ << " : can't find it, maybe it (ino:"<< sop->ino<< ")isn't a normal dir!" << std::endl; return -1; } if (hbl.length() == 0) { // obj has splite if (list_all) { if (frag == frag_t()) { auto item = op.inodes.find(sop->ino); if (item != op.inodes.end()) { inodeno_t tmp = sop->ino; op.pop_op(); std::list frags; item->second->get_meta()->dirfragtree.get_leaves(frags); for (const auto &frag : frags) { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->ino = tmp; nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; nsop->frag = frag; op.push_op(nsop); } } else { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->ino_c = sop->ino; nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; op.push_op(nsop); } return 1; } else { cerr << __func__ << " missing some data (" << oid << ")???" << std::endl; return -1; } } else { if (frag == frag_t()) { inode_backpointer_t bp; if (sop->get_c_ancestor(bp)) { meta_op::sub_op* nsop = new meta_op::sub_op(&op); nsop->ino_c = bp.dirino; nsop->sub_op_t = meta_op::OP_LIST; nsop->sub_ino_t = meta_op::INO_DIR; nsop->trace_level = sop->trace_level + 1; op.push_op(nsop); return 1; } else { cerr << __func__ << "can't find obj(" << oid << ") ,miss ancestors or miss some objs??? " << std::endl; return -1; } } else { cerr << __func__ << "missing some objs(" << oid << ")??? " << std::endl; return -1; } } } fnode_t got_fnode; try { auto p = hbl.cbegin(); ::decode(got_fnode, p); } catch (const buffer::error &err) { cerr << "corrupt fnode header in " << oid << ": " << err.what() << std::endl; return -1; } if (_debug) { std::string format = "json"; Formatter* f = Formatter::create(format); f->enable_line_break(); f->dump_string("type", "--fnode--"); f->open_object_section("fnode"); got_fnode.dump(f); f->close_section(); f->flush(std::cout); std::cout << std::endl; } // print children std::map out_vals; int max_vals = 5; io_meta.omap_get_vals(oid, "", max_vals, &out_vals); bool force_dirty = false; const set *snaps = NULL; unsigned pos = out_vals.size() - 1; std::string last_dname; for (map::iterator p = out_vals.begin(); p != out_vals.end(); ++p, --pos) { string dname; snapid_t last; dentry_key_t::decode_helper(p->first, dname, last); if (_debug) last_dname = dname; try { if (!list_all) { if (show_child(p->first, dname, last, p->second, pos, snaps, &force_dirty, ino, &op) == 1) { return 0; } } else { cout << "dname : " << dname << " " << last << std::endl; if (show_child(p->first, dname, last, p->second, pos, snaps, &force_dirty) == 1) return 0; } } catch (const buffer::error &err) { derr << "Corrupt dentry '" << dname << "' : " << err.what() << "(" << "" << ")" << dendl; return -1; } } while (out_vals.size() == (size_t)max_vals) { out_vals.clear(); io_meta.omap_get_vals(oid, last_dname, max_vals, &out_vals); pos = out_vals.size() - 1; for (map::iterator p = (++out_vals.begin()); p != out_vals.end(); ++p, --pos) { string dname; snapid_t last; dentry_key_t::decode_helper(p->first, dname, last); last_dname = dname; try { if (!list_all) { if (show_child(p->first, dname, last, p->second, pos, snaps, &force_dirty, ino, &op) == 1) { return 0; } } else { cout << "dname : " << dname << " " << last << std::endl; if (show_child(p->first, dname, last, p->second, pos, snaps, &force_dirty) == 1) return 0; } } catch (const buffer::error &err) { derr << "Corrupt dentry '" << dname << "' : " << err.what() << "(" << "" << ")" << dendl; return -1; } } } if (!list_all) { cerr << __func__ << "miss obj(ino:" << ino << ")??? " << std::endl; return -1; } return 0; } int MetaTool::file_meta(meta_op &op) { int r = 0; if (op.top_op()->sub_ino_t == meta_op::INO_DIR) { r = _file_meta(op, io_meta); } else if (op.top_op()->sub_ino_t == meta_op::INO_F) { for (auto i = io_data_v.begin(); i != io_data_v.end(); ++i) if ((r = _file_meta(op, **i)) == 1) break; } if (r == 1) { inode_backpointer_t bp; if (op.top_op()->get_ancestor(bp)) { return 0; } else { std::cerr << "no trace for obj (ino:" << op.top_op()->ino <<")??" << std::endl; return -1; } } else if (op.top_op()->sub_ino_t == meta_op::INO_DIR) { std::cerr << "\tmaybe it's a file(ino:" << op.top_op()->ino << ")" << std::endl; op.top_op()->sub_ino_t = meta_op::INO_F; return 1; } std::cerr << "can't get (ino:" << op.top_op()->ino <<")trace??" << std::endl; return -1; } int MetaTool::_file_meta(meta_op &op, librados::IoCtx& io) { inodeno_t ino = op.top_op()->ino; std::string oid = obj_name(ino); bufferlist pointer_bl; std::map attrset; int r = 0; bool have_data = false; r = io.getxattrs (oid.c_str(), attrset); if (0 == r) { std::stringstream ds; std::string format = "json"; Formatter* f = Formatter::create(format); auto item = attrset.find("parent"); if (item != attrset.end()) { inode_backtrace_t i_bt; try { bufferlist::const_iterator q = item->second.cbegin(); i_bt.decode(q); f->open_array_section("info"); have_data = true; if (i_bt.ancestors.size() > 0) op.ancestors[ino] = i_bt.ancestors[0]; f->dump_string("type", "--i_bt--"); f->open_object_section("parent"); i_bt.dump(f); f->close_section(); } catch (buffer::error &e) { cerr << "failed to decode parent of " << oid << std::endl; return -1; } } else { cerr << oid << " in " << io.get_pool_name() << " , but no parent" << std::endl; return -1; } item = attrset.find("layout"); if (item != attrset.end()) { file_layout_t layout; try { auto q = item->second.cbegin(); layout.decode(q); f->dump_string("type", "--layout--"); f->open_object_section("layout"); layout.dump(f); f->close_section(); } catch (buffer::error &e) { cerr << "failed to decode layout of " << oid << std::endl; return -1; } } else { cerr << oid << " in " << io.get_pool_name() << " , but no layout" << std::endl; } if (have_data) { f->close_section(); f->flush(ds); if (_debug) cout << ino << " : "<< ds.str() << std::endl; return 1; } } return 0; } std::string MetaTool::obj_name(inodeno_t ino, uint64_t offset, const char *suffix) const { char name[60]; snprintf(name, sizeof(name), "%llx.%08llx%s", (long long unsigned)ino, (long long unsigned)offset, suffix ? suffix : ""); return std::string(name); } std::string MetaTool::obj_name(inodeno_t ino, frag_t fg, const char *suffix) const { char name[60]; snprintf(name, sizeof(name), "%llx.%08llx%s", (long long unsigned)ino, (long long unsigned)fg, suffix ? suffix : ""); return std::string(name); } std::string MetaTool::obj_name(const char* ino, uint64_t offset, const char *suffix) const { char name[60]; snprintf(name, sizeof(name), "%s.%08llx%s", ino, (long long unsigned)offset, suffix ? suffix : ""); std::string out = name; transform(out.begin(), out.end(), out.begin(),::tolower); return out; } int MetaTool::show_child(std::string_view key, std::string_view dname, const snapid_t last, bufferlist &bl, const int pos, const std::set *snaps, bool *force_dirty, inodeno_t sp_ino, meta_op* op) { bufferlist::const_iterator q = bl.cbegin(); snapid_t first; ::decode(first, q); // marker char type; ::decode(type, q); if (_debug) std::cout << pos << " type '" << type << "' dname '" << dname << " [" << first << "," << last << "]" << std::endl; // bool stale = false; if (snaps && last != CEPH_NOSNAP) { derr << "!!!! erro !!!!" << dendl; return -1; } // CDentry *dn = NULL; // look for existing dentry for _last_ snap, can't process snap of obj //if *(stale) // dn = lookup_exact_snap(dname, last); //else // dn = lookup(dname, last); if (type == 'L' || type == 'l') { // hard link inodeno_t ino; unsigned char d_type; mempool::mds_co::string alternate_name; CDentry::decode_remote(type, ino, d_type, alternate_name, q); if (sp_ino > 0) { if (sp_ino == ino) { std::cout << "find hard link : " << ino << "," << d_type << std::endl; return 1; } } std::cout << "hard link : " << ino << "," << d_type << std::endl; } else if (type == 'I' || type == 'i') { // inode // load inode data before lookuping up or constructing CInode InodeStore& inode_data = *(new InodeStore); if (type == 'i') { mempool::mds_co::string alternate_name; DECODE_START(2, q); if (struct_v >= 2) decode(alternate_name, q); inode_data.decode(q); DECODE_FINISH(q); } else { inode_data.decode_bare(q); } std::stringstream ds; std::string format = "json"; Formatter* f = Formatter::create(format); f->enable_line_break(); f->open_object_section("meta"); f->dump_unsigned("snapid_t", first); f->dump_unsigned("itype", type); f->open_object_section("store"); inode_data.dump(f); try { if (inode_data.snap_blob.length()) { sr_t srnode; auto p = inode_data.snap_blob.cbegin(); srnode.decode(p); f->open_object_section("snap_blob"); srnode.dump(f); f->close_section(); } } catch (const buffer::error &err) { cerr << "corrupt decode in snap_blob" << ": " << err.what() << std::endl; } f->close_section(); f->close_section(); f->flush(ds); if (sp_ino > 0 && op != NULL && sp_ino == inode_data.inode->ino) { inode_meta_t* tmp = new inode_meta_t(first, type, &inode_data); op->inodes[inode_data.inode->ino] = tmp; op->okeys[inode_data.inode->ino] = key.data(); return 1; } else { delete &inode_data; } if (sp_ino == 0) { cout << ds.str() << std::endl; } } else { std::cerr << __func__ << "unknow type : " << dname << "," << type << std::endl; } return 0; }