]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tool: add function of show/amend fnode 34755/head
authorshenhang <shenhang@kuaishou.com>
Sun, 26 Apr 2020 03:24:51 +0000 (11:24 +0800)
committershenhang <shenhang@kuaishou.com>
Thu, 30 Apr 2020 10:05:59 +0000 (18:05 +0800)
Signed-off-by: Shen Hang <harryshen18@gmail.com>
src/mds/mdstypes.cc
src/mds/mdstypes.h
src/tools/cephfs/MetaTool.cc
src/tools/cephfs/MetaTool.h
src/tools/cephfs/cephfs-meta-injection.cc

index 360a8fc6db5c63b9702e1ef7c8f1f49e5aed0384..6c3038588602b9354920b594a1ec048d287e454f 100644 (file)
@@ -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<nest_info_t*>& 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<fnode_t*>& ls)
 {
   ls.push_back(new fnode_t);
index 3f46860e78b562ad00dc19f8d957d51c5ef5a782..68caee66692e71749e1ee2ed6db6d454781a64e2 100644 (file)
@@ -1076,6 +1076,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<fnode_t*>& ls);
 
   version_t version = 0;
index 06357e527f1aad387c8df23c9b8f5bf2b5a751b0..1371e046ec1bf5446909017281a4fc54cddc9299 100644 (file)
@@ -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<frag_t> 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<string> 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);
index a51933b0df54af9085adbc5a38f839c4eccac182..80d05c7e788d7098ad85ec80d7f7dd157671acb0 100644 (file)
@@ -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):
index 9ccfd0e5dcf714154b10251683a3ece4dbeaf6ab..912c5ae25e2cc13e66c8893036d6026bc956d766 100644 (file)
@@ -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 <conv|listc|showm|amend> -r <fsname:rank> -i <ino>"
+                  << "  cephfs-meta-injection <conv|listc|showm|showfn|amend|amendfn> -r <fsname:rank> -i <ino>"
                   << std::endl;
         std::cout << "example : \n"
                   << "  amend info of inode(1099531628828)\n"