diff --git a/src/tools/cephfs/MetaTool.cc b/src/tools/cephfs/MetaTool.cc index f5894e2f207..bde23f75990 100644 --- a/src/tools/cephfs/MetaTool.cc +++ b/src/tools/cephfs/MetaTool.cc @@ -1,3 +1,5 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab #include #include #include @@ -35,29 +37,33 @@ WRITE_RAW_ENCODER(unsigned char) #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::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::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(); +void MetaTool::usage() +{ + generic_client_usage(); } int MetaTool::main(string& mode, @@ -67,787 +73,808 @@ int MetaTool::main(string& mode, string& out, string& in, bool confirm - ){ - int r = 0; + ) +{ + 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; - } + 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 - const std::vector & data_pools_v = fs->mds_map.get_data_pools(); - for(auto i = data_pools_v.begin(); i != data_pools_v.end(); ++i){ - r = rados.pool_reverse_lookup(*i, &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; - } + // RADOS init + r = rados.init_with_context(g_ceph_context); + if (r < 0) { + cerr << "RADOS unavailable" << 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; + } + + 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; } -} -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; + + 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; } - return 0; + + 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::amend_fnode(string& in, bool confirm){ - meta_op op(_debug, "", in, confirm); + +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_AMEND_FN; + nsop->sub_op_t = meta_op::OP_SHOW_FN; nsop->sub_ino_t = meta_op::INO_DIR; - nsop->ino = 0; + 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_meta_info(string& ino, string& in, bool confirm){ - if (ino != "0" && in != ""){ - inodeno_t i_ino = conv2hexino(ino.c_str()); - 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::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::list_meta_info(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_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::amend_meta_info(string& ino, string& in, bool confirm) +{ + if (ino != "0" && in != "") { + inodeno_t i_ino = conv2hexino(ino.c_str()); + 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::show_meta_info(string& ino, string& out){ - if (ino != "0"){ - inodeno_t i_ino = conv2hexino(ino.c_str()); - meta_op op(_debug, out); +int MetaTool::list_meta_info(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_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 = 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; - 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; + 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(); +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; } - op.release(); - return r; + 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; - } +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; + } + return 0; } -void MetaTool::inode_meta_t::encode(::ceph::bufferlist& bl, uint64_t features){ +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::_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(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.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; + 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 it, maybe it (ino:"<< sop->ino<< ")isn't a normal dir!" << std::endl; - return -1; + if (ret < 0) { + std::cerr << __func__ << " : can't find oid("<< oid << ")" << 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__ << "cann'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 { + { + fnode_t got_fnode; + try { auto p = hbl.cbegin(); ::decode(got_fnode, p); - }catch (const buffer::error &err){ + } 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; } - 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; - } + } else + std::cout << ds.str() << std::endl; + return 0; +} +int MetaTool::list_meta(meta_op &op) +{ + meta_op::sub_op* sop = op.top_op(); - // 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(); + 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); - 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; -} -unsigned long long MetaTool::conv2hexino(const char* ino){ - unsigned long long iino = 0; - std::stringstream conv; - conv << ino; - conv >> iino; - printf("convert to hexadecimal ino %s => %llx \n", ino, iino); - return iino; -} - -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)){ + 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; - }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; + } catch (const buffer::error &err) { + derr << "Corrupt dentry '" << dname << "' : " + << err.what() << "(" << "" << ")" << dendl; + return -1; + } } - - std::cerr << "can't get (ino:" << op.top_op()->ino <<")trace??" << std::endl; + } + + if (!list_all) { + cerr << __func__ << "miss obj(ino:" << ino << ")??? " << std::endl; return -1; + } + return 0; +} +unsigned long long MetaTool::conv2hexino(const char* ino) +{ + unsigned long long iino = 0; + std::stringstream conv; + conv << ino; + conv >> iino; + printf("convert to hexadecimal ino %s => %llx \n", ino, iino); + return iino; } -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; - } +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; } - return 0; + } 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; } -std::string MetaTool::obj_name(inodeno_t ino, uint64_t offset, const char *suffix) const{ + +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); @@ -876,95 +903,93 @@ int MetaTool::show_child(std::string_view key, const std::set *snaps, bool *force_dirty, inodeno_t sp_ino, - meta_op* op){ - bufferlist::const_iterator q = bl.cbegin(); + meta_op* op) +{ + bufferlist::const_iterator q = bl.cbegin(); - snapid_t first; - ::decode(first, q); + 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; + // 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') { + // hard link + inodeno_t ino; + unsigned char d_type; + ::decode(ino, q); + ::decode(d_type, q); + if (sp_ino > 0) { + if (sp_ino == ino) { + std::cout << "find hard link : " << ino << "," << d_type << std::endl; + return 1; + } } - - // CDentry *dn = NULL; - // look for existing dentry for _last_ snap, cann't process snap of obj - //if *(stale) - // dn = lookup_exact_snap(dname, last); - //else - // dn = lookup(dname, last); - if (type == 'L'){ - // hard link - inodeno_t ino; - unsigned char d_type; - ::decode(ino, q); - ::decode(d_type, 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') { - // inode - // load inode data before lookuping up or constructing CInode - InodeStore& inode_data = *(new InodeStore); - inode_data.decode_bare(q); - - std::stringstream ds; - //std::string format = "json-pretty"; - std::string format = "json"; - // Formatter f = new JSONFormatter(false); - 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; - } + std::cout << "hard link : " << ino << "," << d_type << std::endl; + } else if (type == 'I') { + // inode + // load inode data before lookuping up or constructing CInode + InodeStore& inode_data = *(new InodeStore); + 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(); - 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; + } + } catch (const buffer::error &err) { + cerr << "corrupt decode in snap_blob" + << ": " << err.what() << std::endl; } - return 0; + 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; } - diff --git a/src/tools/cephfs/MetaTool.h b/src/tools/cephfs/MetaTool.h index 80d05c7e788..809c8d9b6cf 100644 --- a/src/tools/cephfs/MetaTool.h +++ b/src/tools/cephfs/MetaTool.h @@ -1,3 +1,5 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab #ifndef METATOOL_H__ #define METATOOL_H__ @@ -16,253 +18,256 @@ using std::stack; using ::ceph::bufferlist; class MetaTool : public MDSUtility { - public: - class inode_meta_t{ - public: +public: + class inode_meta_t { + public: inode_meta_t(snapid_t f = CEPH_NOSNAP, char t = 255, InodeStore* i = NULL): - _f(f),_t(t),_i(i){ - }; - snapid_t get_snapid() const { - return _f; - } - InodeStore* get_meta() const { - if (_t == 'I') - return _i; - else - return NULL; - } - int get_type() const{ - return _t; - } - void decode_json(JSONObj *obj); - void encode(::ceph::bufferlist& bl, uint64_t features); - private: - snapid_t _f; - char _t; - InodeStore* _i; + _f(f),_t(t),_i(i) { }; - private: - class meta_op{ - public: + snapid_t get_snapid() const { + return _f; + } + InodeStore* get_meta() const { + if (_t == 'I') + return _i; + else + return NULL; + } + int get_type() const { + return _t; + } + void decode_json(JSONObj *obj); + void encode(::ceph::bufferlist& bl, uint64_t features); + private: + snapid_t _f; + char _t; + InodeStore* _i; + }; +private: + class meta_op { + public: meta_op(bool debug = false, string out = "", string in = "", bool confirm = false): _debug(debug), - _out(out), - _in(in), - _confirm(confirm) - {} - void release(); - typedef enum{ - OP_LIST = 0, - OP_LTRACE, - OP_SHOW, - OP_AMEND, - OP_SHOW_FN, - OP_AMEND_FN, - OP_NO - }op_type; - typedef enum{ - INO_DIR = 0, - INO_F - }ino_type; - static string op_type_name(op_type& t){ - string name; - switch (t){ - case OP_LIST: - name = "list dir"; - break; - case OP_LTRACE: - name = "load trace"; - break; - case OP_SHOW: - name = "show info"; - break; - 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; - default: - name = "unknow op type"; - } - return name; - } - static string ino_type_name(ino_type& t){ - string name; - switch (t){ - case INO_DIR: - name = "dir"; - break; - case INO_F: - name = "file"; - break; - default: - name = "unknow file type"; - } - return name; - } - class sub_op{ - public: - sub_op(meta_op* mop): - trace_level(0), - _proc(false), - _mop(mop) - {} - void print(){ - std::cout << detail() << std::endl; - } - string detail(){ - std::stringstream ds; - ds << " [sub_op]" << op_type_name(sub_op_t) << "|" - << ino_type_name(sub_ino_t) << "|" - << ino << "|" - << frag << "|" - << ino_c << "|" - << trace_level << "|" - << name; - return ds.str(); - } - bool get_c_ancestor(inode_backpointer_t& bp){ - if (!_mop || !ino_c) - return false; - auto item = _mop->ancestors.find(ino_c); - if (item != _mop->ancestors.end()){ - bp = item->second; - return true; - }else - return false; - } - bool get_ancestor(inode_backpointer_t& bp){ - if (!_mop || !ino) - return false; - auto item = _mop->ancestors.find(ino); - if (item != _mop->ancestors.end()){ - bp = item->second; - return true; - }else - return false; - } - op_type sub_op_t; - ino_type sub_ino_t; - inodeno_t ino; - frag_t frag; - inodeno_t ino_c; - unsigned trace_level; - std::string name; - bool _proc; - meta_op* _mop; - }; - - std::map ancestors; - std::map inodes; - std::map okeys; + _out(out), + _in(in), + _confirm(confirm) + {} + void release(); + typedef enum { + OP_LIST = 0, + OP_LTRACE, + OP_SHOW, + OP_AMEND, + OP_SHOW_FN, + OP_AMEND_FN, + OP_NO + } op_type; - void clear_sops(){ - while(!no_sops()) - pop_op(); - } - bool no_sops(){ - return sub_ops.empty(); - } - void push_op(sub_op* sop){ - if (_debug) - std::cout << "<<====" << sop->detail() << std::endl; - sub_ops.push(sop); - } - sub_op* top_op(){ - return sub_ops.top(); - } - void pop_op(){ - sub_op* sop = sub_ops.top(); - if (_debug) - std::cout << "====>>" << sop->detail() << std::endl;; - delete sop; - sub_ops.pop(); - } - string outfile(){ - return _out; - } - string infile(){ - return _in; - } - bool is_debug(){ - return _debug; - } - bool confirm_chg(){ - return _confirm; - } - private: - stack sub_ops; - bool _debug; - string _out; - string _in; - bool _confirm; + typedef enum { + INO_DIR = 0, + INO_F + } ino_type; + + static string op_type_name(op_type& t) { + string name; + switch (t) { + case OP_LIST: + name = "list dir"; + break; + case OP_LTRACE: + name = "load trace"; + break; + case OP_SHOW: + name = "show info"; + break; + 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; + default: + name = "unknow op type"; + } + return name; + } + static string ino_type_name(ino_type& t) { + string name; + switch (t) { + case INO_DIR: + name = "dir"; + break; + case INO_F: + name = "file"; + break; + default: + name = "unknow file type"; + } + return name; + } + class sub_op { + public: + sub_op(meta_op* mop): + trace_level(0), + _proc(false), + _mop(mop) + {} + void print() { + std::cout << detail() << std::endl; + } + string detail() { + std::stringstream ds; + ds << " [sub_op]" << op_type_name(sub_op_t) << "|" + << ino_type_name(sub_ino_t) << "|" + << ino << "|" + << frag << "|" + << ino_c << "|" + << trace_level << "|" + << name; + return ds.str(); + } + bool get_c_ancestor(inode_backpointer_t& bp) { + if (!_mop || !ino_c) + return false; + auto item = _mop->ancestors.find(ino_c); + if (item != _mop->ancestors.end()) { + bp = item->second; + return true; + } else + return false; + } + bool get_ancestor(inode_backpointer_t& bp) { + if (!_mop || !ino) + return false; + auto item = _mop->ancestors.find(ino); + if (item != _mop->ancestors.end()) { + bp = item->second; + return true; + } else + return false; + } + op_type sub_op_t; + ino_type sub_ino_t; + inodeno_t ino; + frag_t frag; + inodeno_t ino_c; + unsigned trace_level; + std::string name; + bool _proc; + meta_op* _mop; }; - MDSRoleSelector role_selector; - mds_rank_t rank; - - // I/O handles - librados::Rados rados; - librados::IoCtx io_meta; - std::vector io_data_v; - librados::IoCtx output; + + std::map ancestors; + std::map inodes; + std::map okeys; + + void clear_sops() { + while(!no_sops()) + pop_op(); + } + bool no_sops() { + return sub_ops.empty(); + } + void push_op(sub_op* sop) { + if (_debug) + std::cout << "<<====" << sop->detail() << std::endl; + sub_ops.push(sop); + } + sub_op* top_op() { + return sub_ops.top(); + } + void pop_op() { + sub_op* sop = sub_ops.top(); + if (_debug) + std::cout << "====>>" << sop->detail() << std::endl;; + delete sop; + sub_ops.pop(); + } + string outfile() { + return _out; + } + string infile() { + return _in; + } + bool is_debug() { + return _debug; + } + bool confirm_chg() { + return _confirm; + } + private: + stack sub_ops; bool _debug; - uint64_t features; + string _out; + string _in; + bool _confirm; + }; + MDSRoleSelector role_selector; + mds_rank_t rank; - std::string obj_name(inodeno_t ino, frag_t fg = frag_t(), const char *suffix = NULL) const; - std::string obj_name(inodeno_t ino, uint64_t offset, const char *suffix = NULL) const; - std::string obj_name(const char* ino, uint64_t offset, const char *suffix = NULL) const; + // I/O handles + librados::Rados rados; + librados::IoCtx io_meta; + std::vector io_data_v; + librados::IoCtx output; + bool _debug; + uint64_t features; - // 0 : continue to find - // 1 : stop to find it - int 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 = 0, - meta_op* op = NULL - ); + std::string obj_name(inodeno_t ino, frag_t fg = frag_t(), const char *suffix = NULL) const; + std::string obj_name(inodeno_t ino, uint64_t offset, const char *suffix = NULL) const; + std::string obj_name(const char* ino, uint64_t offset, const char *suffix = NULL) const; - int process(string& mode, string& ino, string out, string in, bool confirm); - 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): - _debug(debug){} - ~MetaTool(){} - int main(string& mode, - string& rank_str, - string& minfo, - string&ino, - string& out, - string& in, - bool confirm = false - ); + // 0 : continue to find + // 1 : stop to find it + int 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 = 0, + meta_op* op = NULL + ); + + int process(string& mode, string& ino, string out, string in, bool confirm); + 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): + _debug(debug) {} + ~MetaTool() {} + + int main(string& mode, + string& rank_str, + string& minfo, + string&ino, + string& out, + string& in, + bool confirm = false + ); }; #endif // METATOOL_H__ diff --git a/src/tools/cephfs/cephfs-meta-injection.cc b/src/tools/cephfs/cephfs-meta-injection.cc index 912c5ae25e2..79ffbaea31c 100644 --- a/src/tools/cephfs/cephfs-meta-injection.cc +++ b/src/tools/cephfs/cephfs-meta-injection.cc @@ -1,3 +1,5 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab #include #include "common/config.h" #include "common/ceph_argparse.h" @@ -15,87 +17,87 @@ using std::string; using namespace std; static string version = "cephfs-meta-injection v1.1"; -int main(int argc, const char **argv){ - vector args; - argv_to_vec(argc, argv, args); - env_to_vec(args); - auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, - CODE_ENVIRONMENT_UTILITY, 0); - common_init_finish(g_ceph_context); +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); + auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_UTILITY, 0); + common_init_finish(g_ceph_context); - string rank_str, minfo, ino, out,in; - po::options_description general("general options"); - general.add_options() - ("help,h", "produce help message") - ("debug", "show debug info") - ("rank,r", po::value(&rank_str), "the rank of cephfs, default(0) (e.g. -r cephfs_a:0)") - ("minfo", po::value(&minfo), "specify metapool, datapools and rank (e.g. cephfs_metadata_a:cephfs_data_a:0)") - ("ino,i", po::value(&ino), "specify inode. e.g. 1099511627776, you can find it with cmd, 'ls -i'") - ("out,o", po::value(&out), "output file") - ("in", po::value(&in), "input file") - ("yes-i-really-really-mean-it", "need by amend info") - ; + string rank_str, minfo, ino, out,in; + po::options_description general("general options"); + general.add_options() + ("help,h", "produce help message") + ("debug", "show debug info") + ("rank,r", po::value(&rank_str), "the rank of cephfs, default(0) (e.g. -r cephfs_a:0)") + ("minfo", po::value(&minfo), "specify metapool, datapools and rank (e.g. cephfs_metadata_a:cephfs_data_a:0)") + ("ino,i", po::value(&ino), "specify inode. e.g. 1099511627776, you can find it with cmd, 'ls -i'") + ("out,o", po::value(&out), "output file") + ("in", po::value(&in), "input file") + ("yes-i-really-really-mean-it", "need by amend info") + ; - string mode; - po::options_description modeoptions("mode options"); - modeoptions.add_options() - ("mode", po::value(&mode), - "\tconv : convert decimal ino to hex\n" \ - "\tlistc : list all obj of dir\n" \ - "\tshowm : show the info of ino\n" \ - "\tshowfn : show the fnode of dir\n" \ - "\tamend : amend part of the meta data\n" \ - "\tamendfn : amend fnode from file\n" - ); + string mode; + po::options_description modeoptions("mode options"); + modeoptions.add_options() + ("mode", po::value(&mode), + "\tconv : convert decimal ino to hex\n" \ + "\tlistc : list all obj of dir\n" \ + "\tshowm : show the info of ino\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; - p.add("mode", 1); - - po::options_description all("all options"); - all.add(modeoptions).add(general); - po::variables_map vm; - try{ - po::store(po::command_line_parser(argc, argv).options(all).positional(p).allow_unregistered().run(), vm); - }catch(exception &e){ - cerr << "error : " << e.what() << std::endl; - return -1; - } - catch(...){ - cout << "param error" << std::endl; - return 0; - } - - boost::program_options::notify(vm); - if (vm.count("help")){ - std::cout << version << std::endl; - std::cout << "usage : \n" - << " cephfs-meta-injection -r -i " - << std::endl; - std::cout << "example : \n" - << " amend info of inode(1099531628828)\n" - << " cephfs-meta-injection showm -r cephfs_a:0 -i 1099531628828 -o out\n" - << " alter file\n" - << " cephfs-meta-injection amend -r cephfs_a:0 -i 1099531628828 --in out --yes-i-really-mean-it" - << std::endl; - std::cout << all << std::endl; - return 0; - } - - if (mode == "conv"){ - MetaTool::conv2hexino(ino.c_str()); - return 0; - } - - MetaTool mt(vm.count("debug")); - int rc = mt.init(); - if (rc != 0) { - std::cerr << "error in initialization: " << cpp_strerror(rc) << std::endl; - return rc; - } - rc = mt.main(mode, rank_str, minfo, ino, out, in, vm.count("yes-i-really-really-mean-it")); - if (rc != 0) { - std::cerr << "error (" << cpp_strerror(rc) << ")" << std::endl; - return -1; - } + po::positional_options_description p; + p.add("mode", 1); + + po::options_description all("all options"); + all.add(modeoptions).add(general); + po::variables_map vm; + try { + po::store(po::command_line_parser(argc, argv).options(all).positional(p).allow_unregistered().run(), vm); + } catch(exception &e) { + cerr << "error : " << e.what() << std::endl; + return -1; + } catch(...) { + cout << "param error" << std::endl; + return 0; + } + + boost::program_options::notify(vm); + if (vm.count("help")) { + std::cout << version << std::endl; + std::cout << "usage : \n" + << " cephfs-meta-injection -r -i " + << std::endl; + std::cout << "example : \n" + << " amend info of inode(1099531628828)\n" + << " cephfs-meta-injection showm -r cephfs_a:0 -i 1099531628828 -o out\n" + << " alter file\n" + << " cephfs-meta-injection amend -r cephfs_a:0 -i 1099531628828 --in out --yes-i-really-mean-it" + << std::endl; + std::cout << all << std::endl; + return 0; + } + + if (mode == "conv") { + MetaTool::conv2hexino(ino.c_str()); + return 0; + } + + MetaTool mt(vm.count("debug")); + int rc = mt.init(); + if (rc != 0) { + std::cerr << "error in initialization: " << cpp_strerror(rc) << std::endl; return rc; + } + rc = mt.main(mode, rank_str, minfo, ino, out, in, vm.count("yes-i-really-really-mean-it")); + if (rc != 0) { + std::cerr << "error (" << cpp_strerror(rc) << ")" << std::endl; + return -1; + } + return rc; }