diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc index 360a8fc6db5..6c303858860 100644 --- a/src/mds/mdstypes.cc +++ b/src/mds/mdstypes.cc @@ -58,7 +58,7 @@ void frag_info_t::dump(Formatter *f) const void frag_info_t::decode_json(JSONObj *obj){ JSONDecoder::decode_json("version", version, obj, true); - //JSONDecoder::decode_json("mtime", mtime, obj, true); // remove now + JSONDecoder::decode_json("mtime", mtime, obj, true); JSONDecoder::decode_json("num_files", nfiles, obj, true); JSONDecoder::decode_json("num_subdirs", nsubdirs, obj, true); JSONDecoder::decode_json("change_attr", change_attr, obj, true); @@ -142,7 +142,7 @@ void nest_info_t::decode_json(JSONObj *obj){ JSONDecoder::decode_json("rfiles", rfiles, obj, true); JSONDecoder::decode_json("rsubdirs", rsubdirs, obj, true); JSONDecoder::decode_json("rsnaps", rsnaps, obj, true); - //JSONDecoder::decode_json("rctime", rctime, obj, true); // remove now + JSONDecoder::decode_json("rctime", rctime, obj, true); } void nest_info_t::generate_test_instances(std::list& ls) @@ -344,7 +344,16 @@ void fnode_t::dump(Formatter *f) const accounted_rstat.dump(f); f->close_section(); } - +void fnode_t::decode_json(JSONObj *obj){ + JSONDecoder::decode_json("version", version, obj, true); + uint64_t tmp; + JSONDecoder::decode_json("snap_purged_thru", tmp, obj, true); + snap_purged_thru.val = tmp; + JSONDecoder::decode_json("fragstat", fragstat, obj, true); + JSONDecoder::decode_json("accounted_fragstat", accounted_fragstat, obj, true); + JSONDecoder::decode_json("rstat", rstat, obj, true); + JSONDecoder::decode_json("accounted_rstat", accounted_rstat, obj, true); +} void fnode_t::generate_test_instances(std::list& ls) { ls.push_back(new fnode_t); diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index ac4ab10b12f..9ced1b64152 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -1090,6 +1090,7 @@ struct fnode_t { void encode(ceph::buffer::list &bl) const; void decode(ceph::buffer::list::const_iterator& bl); void dump(ceph::Formatter *f) const; + void decode_json(JSONObj *obj); static void generate_test_instances(std::list& ls); version_t version = 0; diff --git a/src/tools/cephfs/MetaTool.cc b/src/tools/cephfs/MetaTool.cc index 7a07d866465..52b3bc36e00 100644 --- a/src/tools/cephfs/MetaTool.cc +++ b/src/tools/cephfs/MetaTool.cc @@ -184,16 +184,43 @@ int MetaTool::main(string& mode, 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 = conv2hexino(ino.c_str()); + 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 = conv2hexino(ino.c_str()); @@ -259,6 +286,12 @@ int MetaTool::op_process(meta_op& op){ 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; } @@ -339,7 +372,129 @@ int MetaTool::_amend_meta(string& k, inode_meta_t& inode_meta, const string& fn, 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__ << " : cantn'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 << std::endl; + return -1; + } + if (oids.size() != 0) + 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); diff --git a/src/tools/cephfs/MetaTool.h b/src/tools/cephfs/MetaTool.h index a51933b0df5..80d05c7e788 100644 --- a/src/tools/cephfs/MetaTool.h +++ b/src/tools/cephfs/MetaTool.h @@ -56,6 +56,8 @@ class MetaTool : public MDSUtility OP_LTRACE, OP_SHOW, OP_AMEND, + OP_SHOW_FN, + OP_AMEND_FN, OP_NO }op_type; typedef enum{ @@ -77,6 +79,12 @@ class MetaTool : public MDSUtility case OP_AMEND: name = "amend info"; break; + case OP_SHOW_FN: + name = "show fnode"; + break; + case OP_AMEND_FN: + name = "amend fnode"; + break; case OP_NO: name = "noop"; break; @@ -228,16 +236,21 @@ class MetaTool : public MDSUtility int show_meta_info(string& ino, string& out); int list_meta_info(string& ino, string& out); int amend_meta_info(string& ino, string& in, bool confirm); + int show_fnode(string& ino, string& out); + int amend_fnode(string& in, bool confirm); int op_process(meta_op &op); int list_meta(meta_op &op); int file_meta(meta_op &op); int show_meta(meta_op &op); int amend_meta(meta_op &op); - + int show_fn(meta_op &op); + int amend_fn(meta_op &op); public: int _file_meta(meta_op &op, librados::IoCtx& io); int _show_meta(inode_meta_t& i, const string& fn); int _amend_meta(string &k, inode_meta_t& i, const string& fn, meta_op& op); + int _show_fn(inode_meta_t& i, const string& fn); + int _amend_fn(const string& fn, bool confirm); static unsigned long long conv2hexino(const char* ino); void usage(); MetaTool(bool debug=false): diff --git a/src/tools/cephfs/cephfs-meta-injection.cc b/src/tools/cephfs/cephfs-meta-injection.cc index 9ccfd0e5dcf..912c5ae25e2 100644 --- a/src/tools/cephfs/cephfs-meta-injection.cc +++ b/src/tools/cephfs/cephfs-meta-injection.cc @@ -43,7 +43,9 @@ int main(int argc, const char **argv){ "\tconv : convert decimal ino to hex\n" \ "\tlistc : list all obj of dir\n" \ "\tshowm : show the info of ino\n" \ - "\tamend : amend part of the meta data\n" + "\tshowfn : show the fnode of dir\n" \ + "\tamend : amend part of the meta data\n" \ + "\tamendfn : amend fnode from file\n" ); po::positional_options_description p; @@ -67,7 +69,7 @@ int main(int argc, const char **argv){ if (vm.count("help")){ std::cout << version << std::endl; std::cout << "usage : \n" - << " cephfs-meta-injection -r -i " + << " cephfs-meta-injection -r -i " << std::endl; std::cout << "example : \n" << " amend info of inode(1099531628828)\n"