]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/cephfs/MetaTool.cc
import ceph quincy 17.2.4
[ceph.git] / ceph / src / tools / cephfs / MetaTool.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #include <string.h>
4 #include <map>
5 #include <sstream>
6 #include <fstream>
7
8 #include "include/types.h"
9 #include "common/Formatter.h"
10 #include "common/ceph_argparse.h"
11 #include "common/errno.h"
12 #include "osdc/Journaler.h"
13 #include "mds/mdstypes.h"
14 #include "mds/LogEvent.h"
15 #include "mds/InoTable.h"
16 #include "mds/CDentry.h"
17
18 #include "mds/events/ENoOp.h"
19 #include "mds/events/EUpdate.h"
20
21 #include "mds/JournalPointer.h"
22 // #include "JournalScanner.h"
23 // #include "EventOutput.h"
24 // #include "Dumper.h"
25 // #include "Resetter.h"
26
27 // #include "JournalTool.h"
28 #include "MetaTool.h"
29 #include "type_helper.hpp"
30 #include "include/object.h"
31
32 WRITE_RAW_ENCODER(char)
33 WRITE_RAW_ENCODER(unsigned char)
34
35 #define dout_context g_ceph_context
36 #define dout_subsys ceph_subsys_mds
37 #undef dout_prefix
38 #define dout_prefix *_dout << __func__ << ": "
39
40 using namespace std;
41
42 void MetaTool::meta_op::release()
43 {
44 for (const auto& i : inodes) {
45 delete i.second;
46 }
47
48 while (!sub_ops.empty()) {
49 delete sub_ops.top();
50 sub_ops.pop();
51 }
52 }
53
54 void MetaTool::inode_meta_t::decode_json(JSONObj *obj)
55 {
56 unsigned long long tmp;
57 JSONDecoder::decode_json("snapid_t", tmp, obj, true);
58 _f.val = tmp;
59 JSONDecoder::decode_json("itype", tmp, obj, true);
60 _t = tmp;
61 if (NULL == _i)
62 _i = new InodeStore;
63 JSONDecoder::decode_json("store", *_i, obj, true);
64 }
65
66 void MetaTool::usage()
67 {
68 generic_client_usage();
69 }
70
71 int MetaTool::main(string& mode,
72 string& rank_str,
73 string& minfo,
74 string&ino,
75 string& out,
76 string& in,
77 bool confirm
78 )
79 {
80 int r = 0;
81
82 std::string manual_meta_pool;
83 std::string manual_data_pool;
84 std::string manual_rank_num;
85 bool manual_mode = false;
86 if (minfo != "") {
87 vector<string> v;
88 string_split(minfo, v);
89 manual_meta_pool = v.size() >= 1 ? v[0] : "";
90 manual_data_pool = v.size() >= 2 ? v[1] : "";
91 manual_rank_num = v.size() >= 3 ? v[2] : "";
92 std::cout << "("<< minfo<< ")=>"
93 << " mpool: " << manual_meta_pool
94 << " dpool: " << manual_data_pool
95 << " rank: " << manual_rank_num
96 << std::endl;
97 if (!manual_meta_pool.empty() && !manual_data_pool.empty() && !manual_rank_num.empty()) {
98 std::cout << "you specify rank: " << manual_rank_num
99 << " mpool: " << manual_meta_pool
100 << " dpool: " << manual_data_pool
101 << "\nstart manual mode!!"<< std::endl;
102 manual_mode = true;
103 }
104 }
105
106 // RADOS init
107 r = rados.init_with_context(g_ceph_context);
108 if (r < 0) {
109 cerr << "RADOS unavailable" << std::endl;
110 return r;
111 }
112
113 if (_debug)
114 cout << "MetaTool: connecting to RADOS..." << std::endl;
115 r = rados.connect();
116 if (r < 0) {
117 cerr << "couldn't connect to cluster: " << cpp_strerror(r) << std::endl;
118 return r;
119 }
120
121 if (!manual_mode) {
122 r = role_selector.parse(*fsmap, rank_str);
123 if (r != 0) {
124 cerr << "Couldn't determine MDS rank." << std::endl;
125 return r;
126 }
127
128 auto fs = fsmap->get_filesystem(role_selector.get_ns());
129 assert(fs != nullptr);
130
131 // prepare io for meta pool
132 int64_t const pool_id = fs->mds_map.get_metadata_pool();
133 features = fs->mds_map.get_up_features();
134 if (features == 0)
135 features = CEPH_FEATURES_SUPPORTED_DEFAULT;
136 else if (features != CEPH_FEATURES_SUPPORTED_DEFAULT) {
137 cout << "I think we need to check the feature! : " << features << std::endl;
138 return -1;
139 }
140
141 std::string pool_name;
142 r = rados.pool_reverse_lookup(pool_id, &pool_name);
143 if (r < 0) {
144 cerr << "Pool " << pool_id << " named in MDS map not found in RADOS!" << std::endl;
145 return r;
146 }
147
148 if (_debug)
149 cout << "MetaTool: creating IoCtx.." << std::endl;
150 r = rados.ioctx_create(pool_name.c_str(), io_meta);
151 assert(r == 0);
152 output.dup(io_meta);
153
154 // prepare io for data pool
155 for (const auto p : fs->mds_map.get_data_pools()) {
156 r = rados.pool_reverse_lookup(p, &pool_name);
157 if (r < 0) {
158 cerr << "Pool " << pool_id << " named in MDS map not found in RADOS!" << std::endl;
159 return r;
160 }
161 librados::IoCtx* io_data = new librados::IoCtx;
162 r = rados.ioctx_create(pool_name.c_str(), *io_data);
163 assert(r == 0);
164 io_data_v.push_back(io_data);
165 }
166
167 for (auto role : role_selector.get_roles()) {
168 rank = role.rank;
169
170 r = process(mode, ino, out, in, confirm);
171 cout << "executing for rank " << rank << " op[" <<mode<< "] ret : " << r << std::endl;
172 }
173
174 } else {
175 features = CEPH_FEATURES_SUPPORTED_DEFAULT;
176 r = rados.ioctx_create(manual_meta_pool.c_str(), io_meta);
177 assert(r == 0);
178
179 librados::IoCtx* io_data = new librados::IoCtx;
180 r = rados.ioctx_create(manual_data_pool.c_str(), *io_data);
181 assert(r == 0);
182 io_data_v.push_back(io_data);
183
184
185 rank = conv_t<int>(manual_rank_num);
186 r = process(mode, ino, out, in, confirm);
187 cout << "op[" << mode << "] ret : " << r << std::endl;
188 }
189 return r;
190 }
191
192 int MetaTool::process(string& mode, string& ino, string out, string in, bool confirm)
193 {
194 if (mode == "showm") {
195 return show_meta_info(ino, out);
196 } else if (mode == "showfn") {
197 return show_fnode(ino, out);
198 } else if (mode == "listc") {
199 return list_meta_info(ino, out);
200 } else if (mode == "amend") {
201 return amend_meta_info(ino, in, confirm);
202 } else if (mode == "amendfn") {
203 return amend_fnode(in, confirm);
204 } else {
205 cerr << "bad command '" << mode << "'" << std::endl;
206 return -EINVAL;
207 }
208 }
209 int MetaTool::show_fnode(string& ino, string& out)
210 {
211 if (ino != "0") {
212 inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0);
213 meta_op op(_debug, out);
214 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
215 nsop->sub_op_t = meta_op::OP_SHOW_FN;
216 nsop->sub_ino_t = meta_op::INO_DIR;
217 nsop->ino = i_ino;
218 op.push_op(nsop);
219 return op_process(op);
220 } else {
221 cerr << "parameter error? : ino = " << ino << std::endl;
222 }
223 return 0;
224 }
225 int MetaTool::amend_fnode(string& in, bool confirm)
226 {
227 meta_op op(_debug, "", in, confirm);
228 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
229 nsop->sub_op_t = meta_op::OP_AMEND_FN;
230 nsop->sub_ino_t = meta_op::INO_DIR;
231 nsop->ino = 0;
232 op.push_op(nsop);
233 return op_process(op);
234 }
235 int MetaTool::amend_meta_info(string& ino, string& in, bool confirm)
236 {
237 if (ino != "0" && in != "") {
238 inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0);
239 meta_op op(_debug, "", in, confirm);
240 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
241 nsop->sub_op_t = meta_op::OP_AMEND;
242 nsop->sub_ino_t = meta_op::INO_DIR;
243 nsop->ino = i_ino;
244 op.push_op(nsop);
245 return op_process(op);
246 } else {
247 cerr << "parameter error? : ino = " << ino << std::endl;
248 }
249 return 0;
250 }
251 int MetaTool::list_meta_info(string& ino, string& out)
252 {
253 if (ino != "0") {
254 inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0);
255 meta_op op(_debug, out);
256 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
257 nsop->sub_op_t = meta_op::OP_LIST;
258 nsop->sub_ino_t = meta_op::INO_DIR;
259 nsop->ino = i_ino;
260 op.push_op(nsop);
261 return op_process(op);
262 } else {
263 cerr << "parameter error? : ino = " << ino << std::endl;
264 }
265 return 0;
266 }
267 int MetaTool::show_meta_info(string& ino, string& out)
268 {
269 if (ino != "0") {
270 inodeno_t i_ino = std::stoull(ino.c_str(), nullptr, 0);
271 meta_op op(_debug, out);
272
273 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
274 nsop->sub_op_t = meta_op::OP_SHOW;
275 nsop->sub_ino_t = meta_op::INO_DIR;
276 nsop->ino = i_ino;
277 op.push_op(nsop);
278 return op_process(op);
279 } else {
280 cerr << "parameter error? : ino = " << ino << std::endl;
281 }
282 return 0;
283 }
284
285 int MetaTool::op_process(meta_op& op)
286 {
287 int r = 0;
288 while (!op.no_sops()) {
289 if (_debug)
290 std::cout << "process : " << op.top_op()->detail() << std::endl;
291 switch(op.top_op()->sub_op_t) {
292 case meta_op::OP_LIST:
293 r = list_meta(op);
294 break;
295 case meta_op::OP_LTRACE:
296 r = file_meta(op);
297 break;
298 case meta_op::OP_SHOW:
299 r = show_meta(op);
300 break;
301 case meta_op::OP_AMEND:
302 r = amend_meta(op);
303 break;
304 case meta_op::OP_SHOW_FN:
305 r = show_fn(op);
306 break;
307 case meta_op::OP_AMEND_FN:
308 r = amend_fn(op);
309 break;
310 default:
311 cerr << "unknow op" << std::endl;
312 }
313 if (r == 0)
314 op.pop_op();
315 else if (r < 0)
316 op.clear_sops();
317 }
318 op.release();
319 return r;
320 }
321
322 int MetaTool::amend_meta(meta_op &op)
323 {
324 meta_op::sub_op* sop = op.top_op();
325 auto item = op.inodes.find(sop->ino);
326 auto item_k = op.okeys.find(sop->ino);
327 if (item != op.inodes.end() && item_k != op.okeys.end()) {
328 if (_amend_meta(item_k->second, *(item->second), op.infile(), op) < 0)
329 return -1;
330 } else {
331 if (op.inodes.empty()) {
332 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
333 nsop->sub_op_t = meta_op::OP_LIST;
334 nsop->sub_ino_t = meta_op::INO_DIR;
335 nsop->trace_level = 0;
336 nsop->ino_c = sop->ino;
337 op.push_op(nsop);
338 return 1;
339 } else {
340 return -1;
341 }
342 }
343 return 0;
344 }
345
346 void MetaTool::inode_meta_t::encode(::ceph::bufferlist& bl, uint64_t features)
347 {
348 ::encode(_f, bl);
349 ::encode(_t, bl);
350 _i->encode_bare(bl, features);
351 }
352 int MetaTool::_amend_meta(string& k, inode_meta_t& inode_meta, const string& fn, meta_op& op)
353 {
354 JSONParser parser;
355 if (!parser.parse(fn.c_str())) {
356 cout << "Error parsing create user response" << std::endl;
357 return -1;
358 }
359
360 try {
361 inode_meta.decode_json(&parser);
362 } catch (JSONDecoder::err& e) {
363 cout << "failed to decode JSON input: " << e.what() << std::endl;
364 return -1;
365 }
366
367 if (!op.confirm_chg() || op.is_debug()) {
368 cout << "you will amend info of inode ==>: " << std::endl;
369 _show_meta(inode_meta, "");
370 }
371
372 if (!op.confirm_chg()) {
373 cout << "warning: this operation is irreversibl!!!\n"
374 << " You must confirm that all logs of mds have been flushed!!!\n"
375 << " if you want amend it, please add --yes-i-really-really-mean-it!!!"
376 << std::endl;
377 return -1;
378 }
379
380 bufferlist bl;
381 inode_meta.encode(bl, features);
382 map<string, bufferlist> to_set;
383 to_set[k].swap(bl);
384 inode_backpointer_t bp;
385 if (!op.top_op()->get_ancestor(bp))
386 return -1;
387 frag_t frag;
388 auto item = op.inodes.find(bp.dirino);
389 if (item != op.inodes.end()) {
390 frag = item->second->get_meta()->pick_dirfrag(bp.dname);
391 }
392 string oid = obj_name(bp.dirino, frag);
393 int ret = io_meta.omap_set(oid, to_set);
394 to_set.clear();
395 return ret;
396 }
397 int MetaTool::show_fn(meta_op &op)
398 {
399 meta_op::sub_op* sop = op.top_op();
400 auto item = op.inodes.find(sop->ino);
401 if (item != op.inodes.end()) {
402 if (_show_fn(*(item->second), op.outfile()) < 0)
403 return -1;
404 } else {
405 if (op.inodes.empty()) {
406 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
407 nsop->sub_op_t = meta_op::OP_LIST;
408 nsop->sub_ino_t = meta_op::INO_DIR;
409 nsop->trace_level = 0;
410 nsop->ino_c = sop->ino;
411 op.push_op(nsop);
412 return 1;
413 } else
414 return -1;
415 }
416 return 0;
417 }
418 int MetaTool::_show_fn(inode_meta_t& inode_meta, const string& fn)
419 {
420 std::list<frag_t> frags;
421 inode_meta.get_meta()->dirfragtree.get_leaves(frags);
422 std::stringstream ds;
423 std::string format = "json";
424 std::string oids;
425 Formatter* f = Formatter::create(format);
426 f->enable_line_break();
427 f->open_object_section("fnodes");
428 for (const auto &frag : frags) {
429 bufferlist hbl;
430 string oid = obj_name(inode_meta.get_meta()->inode->ino, frag);
431 int ret = io_meta.omap_get_header(oid, &hbl);
432 if (ret < 0) {
433 std::cerr << __func__ << " : can't find oid("<< oid << ")" << std::endl;
434 return -1;
435 }
436 {
437 fnode_t got_fnode;
438 try {
439 auto p = hbl.cbegin();
440 ::decode(got_fnode, p);
441 } catch (const buffer::error &err) {
442 cerr << "corrupt fnode header in " << oid
443 << ": " << err.what() << std::endl;
444 return -1;
445 }
446 if (!oids.empty())
447 oids += ",";
448 oids += oid;
449 f->open_object_section(oid.c_str());
450 got_fnode.dump(f);
451 f->close_section();
452 }
453 }
454 f->dump_string("oids", oids.c_str());
455 f->close_section();
456 f->flush(ds);
457 if (fn != "") {
458 ofstream o;
459 o.open(fn);
460 if (o) {
461 o << ds.str();
462 o.close();
463 } else {
464 cout << "out to file (" << fn << ") failed" << std::endl;
465 cout << ds.str() << std::endl;
466 }
467 } else
468 std::cout << ds.str() << std::endl;
469 return 0;
470 }
471 int MetaTool::amend_fn(meta_op &op)
472 {
473 if (_amend_fn(op.infile(), op.confirm_chg()) < 0)
474 return -1;
475 return 0;
476 }
477 int MetaTool::_amend_fn(const string& fn, bool confirm)
478 {
479 JSONParser parser;
480 if (!parser.parse(fn.c_str())) {
481 cout << "Error parsing create user response : " << fn << std::endl;
482 return -1;
483 }
484 if (!confirm) {
485 cout << "warning: this operation is irreversibl!!!\n"
486 << " You must confirm that all logs of mds have been flushed!!!\n"
487 << " if you want amend it, please add --yes-i-really-really-mean-it!!!"
488 << std::endl;
489 return -1;
490 }
491 try {
492 string tmp;
493 JSONDecoder::decode_json("oids", tmp, &parser, true);
494 string::size_type pos1, pos2;
495 vector<string> v;
496 string c = ",";
497 pos2 = tmp.find(c);
498 pos1 = 0;
499 while (string::npos != pos2) {
500 v.push_back(tmp.substr(pos1, pos2-pos1));
501 pos1 = pos2 + c.size();
502 pos2 = tmp.find(c, pos1);
503 }
504 if (pos1 != tmp.length())
505 v.push_back(tmp.substr(pos1));
506 int ret = 0;
507 for (auto i : v) {
508 cout << "amend frag : " << i << "..." << std::endl;
509 fnode_t fnode;
510 JSONDecoder::decode_json(i.c_str(), fnode, &parser, true);
511 bufferlist bl;
512 fnode.encode(bl);
513 ret = io_meta.omap_set_header(i, bl);
514 if (ret < 0)
515 return ret;
516 }
517 } catch (JSONDecoder::err& e) {
518 cout << "failed to decode JSON input: " << e.what() << std::endl;
519 return -1;
520 }
521 return 0;
522 }
523 int MetaTool::show_meta(meta_op &op)
524 {
525 meta_op::sub_op* sop = op.top_op();
526 auto item = op.inodes.find(sop->ino);
527 if (item != op.inodes.end()) {
528 if (_show_meta(*(item->second), op.outfile()) < 0)
529 return -1;
530 } else {
531 if (op.inodes.empty()) {
532 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
533 nsop->sub_op_t = meta_op::OP_LIST;
534 nsop->sub_ino_t = meta_op::INO_DIR;
535 nsop->trace_level = 0;
536 nsop->ino_c = sop->ino;
537 op.push_op(nsop);
538 return 1;
539 } else {
540 return -1;
541 }
542 }
543 return 0;
544 }
545 int MetaTool::_show_meta(inode_meta_t& inode_meta, const string& fn)
546 {
547 std::stringstream ds;
548 std::string format = "json";
549 InodeStore& inode_data = *inode_meta.get_meta();
550 Formatter* f = Formatter::create(format);
551 f->enable_line_break();
552 f->open_object_section("meta");
553 f->dump_unsigned("snapid_t", inode_meta.get_snapid());
554 f->dump_unsigned("itype", inode_meta.get_type());
555 f->open_object_section("store");
556 inode_data.dump(f);
557 try {
558 if (inode_data.snap_blob.length()) {
559 sr_t srnode;
560 auto p = inode_data.snap_blob.cbegin();
561 decode(srnode, p);
562 f->open_object_section("snap_blob");
563 srnode.dump(f);
564 f->close_section();
565 }
566 } catch (const buffer::error &err) {
567 cerr << "corrupt decode in snap_blob"
568 << ": " << err.what() << std::endl;
569 return -1;
570 }
571
572 f->close_section();
573 f->close_section();
574 f->flush(ds);
575
576 if (fn != "") {
577 ofstream o;
578 o.open(fn);
579 if (o) {
580 o << ds.str();
581 o.close();
582 } else {
583 cout << "out to file (" << fn << ") failed" << std::endl;
584 cout << ds.str() << std::endl;
585 }
586
587 } else
588 std::cout << ds.str() << std::endl;
589 return 0;
590 }
591 int MetaTool::list_meta(meta_op &op)
592 {
593 meta_op::sub_op* sop = op.top_op();
594
595 bool list_all = false;
596 string oid;
597 inodeno_t ino = sop->ino_c;
598 frag_t frag = sop->frag;
599
600 if (sop->ino_c == 0) {
601 list_all = true;
602 oid = obj_name(sop->ino, frag);
603 } else {
604 if (_debug)
605 std::cout << __func__ << " : " << sop->trace_level << " " << op.ancestors.size() << std::endl;
606 inode_backpointer_t bp;
607 if (sop->get_c_ancestor(bp)) {
608 auto item = op.inodes.find(bp.dirino);
609 if (item != op.inodes.end()) {
610 frag = item->second->get_meta()->pick_dirfrag(bp.dname);
611 }
612 oid = obj_name(bp.dirino, frag);
613 } else {
614 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
615 nsop->ino = sop->ino_c;
616 nsop->sub_op_t = meta_op::OP_LTRACE;
617 nsop->sub_ino_t = meta_op::INO_DIR;
618 op.push_op(nsop);
619 return 1;
620 }
621 }
622 if (_debug)
623 std::cout << __func__ << " : " << string(list_all?"listall ":"info ") << oid << " "<< ino << std::endl;
624 bufferlist hbl;
625 int ret = io_meta.omap_get_header(oid, &hbl);
626 if (ret < 0) {
627 std::cerr << __func__ << " : can't find it, maybe it (ino:"<< sop->ino<< ")isn't a normal dir!" << std::endl;
628 return -1;
629 }
630
631 if (hbl.length() == 0) { // obj has splite
632 if (list_all) {
633 if (frag == frag_t()) {
634 auto item = op.inodes.find(sop->ino);
635 if (item != op.inodes.end()) {
636 inodeno_t tmp = sop->ino;
637 op.pop_op();
638 std::list<frag_t> frags;
639 item->second->get_meta()->dirfragtree.get_leaves(frags);
640 for (const auto &frag : frags) {
641 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
642 nsop->ino = tmp;
643 nsop->sub_op_t = meta_op::OP_LIST;
644 nsop->sub_ino_t = meta_op::INO_DIR;
645 nsop->frag = frag;
646 op.push_op(nsop);
647 }
648 } else {
649 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
650 nsop->ino_c = sop->ino;
651 nsop->sub_op_t = meta_op::OP_LIST;
652 nsop->sub_ino_t = meta_op::INO_DIR;
653 op.push_op(nsop);
654 }
655 return 1;
656 } else {
657 cerr << __func__ << " missing some data (" << oid << ")???" << std::endl;
658 return -1;
659 }
660 } else {
661 if (frag == frag_t()) {
662 inode_backpointer_t bp;
663 if (sop->get_c_ancestor(bp)) {
664 meta_op::sub_op* nsop = new meta_op::sub_op(&op);
665 nsop->ino_c = bp.dirino;
666 nsop->sub_op_t = meta_op::OP_LIST;
667 nsop->sub_ino_t = meta_op::INO_DIR;
668 nsop->trace_level = sop->trace_level + 1;
669 op.push_op(nsop);
670 return 1;
671 } else {
672 cerr << __func__ << "can't find obj(" << oid << ") ,miss ancestors or miss some objs??? " << std::endl;
673 return -1;
674 }
675 } else {
676 cerr << __func__ << "missing some objs(" << oid << ")??? " << std::endl;
677 return -1;
678 }
679 }
680 }
681
682 fnode_t got_fnode;
683 try {
684 auto p = hbl.cbegin();
685 ::decode(got_fnode, p);
686 } catch (const buffer::error &err) {
687 cerr << "corrupt fnode header in " << oid
688 << ": " << err.what() << std::endl;
689 return -1;
690 }
691
692 if (_debug) {
693 std::string format = "json";
694 Formatter* f = Formatter::create(format);
695 f->enable_line_break();
696 f->dump_string("type", "--fnode--");
697 f->open_object_section("fnode");
698 got_fnode.dump(f);
699 f->close_section();
700 f->flush(std::cout);
701 std::cout << std::endl;
702 }
703
704 // print children
705 std::map<string, bufferlist> out_vals;
706 int max_vals = 5;
707 io_meta.omap_get_vals(oid, "", max_vals, &out_vals);
708
709 bool force_dirty = false;
710 const set<snapid_t> *snaps = NULL;
711 unsigned pos = out_vals.size() - 1;
712 std::string last_dname;
713 for (map<string, bufferlist>::iterator p = out_vals.begin();
714 p != out_vals.end();
715 ++p, --pos) {
716 string dname;
717 snapid_t last;
718 dentry_key_t::decode_helper(p->first, dname, last);
719 if (_debug)
720 last_dname = dname;
721 try {
722 if (!list_all) {
723 if (show_child(p->first, dname, last, p->second, pos, snaps,
724 &force_dirty, ino, &op) == 1) {
725 return 0;
726 }
727 } else {
728 cout << "dname : " << dname << " " << last << std::endl;
729 if (show_child(p->first, dname, last, p->second, pos, snaps,
730 &force_dirty) == 1)
731 return 0;
732 }
733 } catch (const buffer::error &err) {
734 derr << "Corrupt dentry '" << dname << "' : "
735 << err.what() << "(" << "" << ")" << dendl;
736 return -1;
737 }
738 }
739 while (out_vals.size() == (size_t)max_vals) {
740 out_vals.clear();
741 io_meta.omap_get_vals(oid, last_dname, max_vals, &out_vals);
742 pos = out_vals.size() - 1;
743 for (map<string, bufferlist>::iterator p = (++out_vals.begin());
744 p != out_vals.end();
745 ++p, --pos) {
746 string dname;
747 snapid_t last;
748 dentry_key_t::decode_helper(p->first, dname, last);
749 last_dname = dname;
750 try {
751 if (!list_all) {
752 if (show_child(p->first, dname, last, p->second, pos, snaps,
753 &force_dirty, ino, &op) == 1) {
754 return 0;
755 }
756 } else {
757 cout << "dname : " << dname << " " << last << std::endl;
758 if (show_child(p->first, dname, last, p->second, pos, snaps,
759 &force_dirty) == 1)
760 return 0;
761 }
762 } catch (const buffer::error &err) {
763 derr << "Corrupt dentry '" << dname << "' : "
764 << err.what() << "(" << "" << ")" << dendl;
765 return -1;
766 }
767 }
768 }
769
770 if (!list_all) {
771 cerr << __func__ << "miss obj(ino:" << ino << ")??? " << std::endl;
772 return -1;
773 }
774 return 0;
775 }
776
777 int MetaTool::file_meta(meta_op &op)
778 {
779 int r = 0;
780 if (op.top_op()->sub_ino_t == meta_op::INO_DIR) {
781 r = _file_meta(op, io_meta);
782 } else if (op.top_op()->sub_ino_t == meta_op::INO_F) {
783 for (auto i = io_data_v.begin(); i != io_data_v.end(); ++i)
784 if ((r = _file_meta(op, **i)) == 1)
785 break;
786 }
787 if (r == 1) {
788 inode_backpointer_t bp;
789 if (op.top_op()->get_ancestor(bp)) {
790 return 0;
791 } else {
792 std::cerr << "no trace for obj (ino:" << op.top_op()->ino <<")??" << std::endl;
793 return -1;
794 }
795 } else if (op.top_op()->sub_ino_t == meta_op::INO_DIR) {
796 std::cerr << "\tmaybe it's a file(ino:" << op.top_op()->ino << ")" << std::endl;
797 op.top_op()->sub_ino_t = meta_op::INO_F;
798 return 1;
799 }
800
801 std::cerr << "can't get (ino:" << op.top_op()->ino <<")trace??" << std::endl;
802 return -1;
803 }
804
805 int MetaTool::_file_meta(meta_op &op, librados::IoCtx& io)
806 {
807 inodeno_t ino = op.top_op()->ino;
808 std::string oid = obj_name(ino);
809 bufferlist pointer_bl;
810 std::map<std::string, bufferlist> attrset;
811 int r = 0;
812 bool have_data = false;
813 r = io.getxattrs (oid.c_str(), attrset);
814 if (0 == r) {
815 std::stringstream ds;
816 std::string format = "json";
817 Formatter* f = Formatter::create(format);
818 auto item = attrset.find("parent");
819 if (item != attrset.end()) {
820 inode_backtrace_t i_bt;
821 try {
822 bufferlist::const_iterator q = item->second.cbegin();
823 i_bt.decode(q);
824 f->open_array_section("info");
825 have_data = true;
826 if (i_bt.ancestors.size() > 0)
827 op.ancestors[ino] = i_bt.ancestors[0];
828 f->dump_string("type", "--i_bt--");
829 f->open_object_section("parent");
830 i_bt.dump(f);
831 f->close_section();
832 } catch (buffer::error &e) {
833 cerr << "failed to decode parent of " << oid << std::endl;
834 return -1;
835 }
836 } else {
837 cerr << oid << " in " << io.get_pool_name() << " , but no parent" << std::endl;
838 return -1;
839 }
840
841 item = attrset.find("layout");
842 if (item != attrset.end()) {
843 file_layout_t layout;
844 try {
845 auto q = item->second.cbegin();
846 layout.decode(q);
847 f->dump_string("type", "--layout--");
848 f->open_object_section("layout");
849 layout.dump(f);
850 f->close_section();
851
852 } catch (buffer::error &e) {
853 cerr << "failed to decode layout of " << oid << std::endl;
854 return -1;
855 }
856 } else {
857 cerr << oid << " in " << io.get_pool_name() << " , but no layout" << std::endl;
858 }
859 if (have_data) {
860 f->close_section();
861 f->flush(ds);
862 if (_debug)
863 cout << ino << " : "<< ds.str() << std::endl;
864 return 1;
865 }
866 }
867 return 0;
868 }
869 std::string MetaTool::obj_name(inodeno_t ino, uint64_t offset, const char *suffix) const
870 {
871 char name[60];
872 snprintf(name, sizeof(name), "%llx.%08llx%s", (long long unsigned)ino, (long long unsigned)offset, suffix ? suffix : "");
873 return std::string(name);
874 }
875 std::string MetaTool::obj_name(inodeno_t ino, frag_t fg, const char *suffix) const
876 {
877 char name[60];
878 snprintf(name, sizeof(name), "%llx.%08llx%s", (long long unsigned)ino, (long long unsigned)fg, suffix ? suffix : "");
879 return std::string(name);
880 }
881
882 std::string MetaTool::obj_name(const char* ino, uint64_t offset, const char *suffix) const
883 {
884 char name[60];
885 snprintf(name, sizeof(name), "%s.%08llx%s", ino, (long long unsigned)offset, suffix ? suffix : "");
886 std::string out = name;
887 transform(out.begin(), out.end(), out.begin(),::tolower);
888 return out;
889 }
890
891 int MetaTool::show_child(std::string_view key,
892 std::string_view dname,
893 const snapid_t last,
894 bufferlist &bl,
895 const int pos,
896 const std::set<snapid_t> *snaps,
897 bool *force_dirty,
898 inodeno_t sp_ino,
899 meta_op* op)
900 {
901 bufferlist::const_iterator q = bl.cbegin();
902
903 snapid_t first;
904 ::decode(first, q);
905
906 // marker
907 char type;
908 ::decode(type, q);
909
910 if (_debug)
911 std::cout << pos << " type '" << type << "' dname '" << dname
912 << " [" << first << "," << last << "]"
913 << std::endl;
914 // bool stale = false;
915 if (snaps && last != CEPH_NOSNAP) {
916 derr << "!!!! erro !!!!" << dendl;
917 return -1;
918 }
919
920 // CDentry *dn = NULL;
921 // look for existing dentry for _last_ snap, can't process snap of obj
922 //if *(stale)
923 // dn = lookup_exact_snap(dname, last);
924 //else
925 // dn = lookup(dname, last);
926 if (type == 'L' || type == 'l') {
927 // hard link
928 inodeno_t ino;
929 unsigned char d_type;
930 mempool::mds_co::string alternate_name;
931
932 CDentry::decode_remote(type, ino, d_type, alternate_name, q);
933
934 if (sp_ino > 0) {
935 if (sp_ino == ino) {
936 std::cout << "find hard link : " << ino << "," << d_type << std::endl;
937 return 1;
938 }
939 }
940
941 std::cout << "hard link : " << ino << "," << d_type << std::endl;
942 } else if (type == 'I' || type == 'i') {
943 // inode
944 // load inode data before lookuping up or constructing CInode
945 InodeStore& inode_data = *(new InodeStore);
946 if (type == 'i') {
947 mempool::mds_co::string alternate_name;
948
949 DECODE_START(2, q);
950 if (struct_v >= 2)
951 decode(alternate_name, q);
952 inode_data.decode(q);
953 DECODE_FINISH(q);
954 } else {
955 inode_data.decode_bare(q);
956 }
957
958 std::stringstream ds;
959 std::string format = "json";
960 Formatter* f = Formatter::create(format);
961 f->enable_line_break();
962 f->open_object_section("meta");
963 f->dump_unsigned("snapid_t", first);
964 f->dump_unsigned("itype", type);
965 f->open_object_section("store");
966 inode_data.dump(f);
967 try {
968 if (inode_data.snap_blob.length()) {
969 sr_t srnode;
970 auto p = inode_data.snap_blob.cbegin();
971 srnode.decode(p);
972 f->open_object_section("snap_blob");
973 srnode.dump(f);
974 f->close_section();
975 }
976 } catch (const buffer::error &err) {
977 cerr << "corrupt decode in snap_blob"
978 << ": " << err.what() << std::endl;
979 }
980 f->close_section();
981 f->close_section();
982 f->flush(ds);
983
984 if (sp_ino > 0 && op != NULL && sp_ino == inode_data.inode->ino) {
985 inode_meta_t* tmp = new inode_meta_t(first, type, &inode_data);
986 op->inodes[inode_data.inode->ino] = tmp;
987 op->okeys[inode_data.inode->ino] = key.data();
988 return 1;
989 } else {
990 delete &inode_data;
991 }
992
993 if (sp_ino == 0) {
994 cout << ds.str() << std::endl;
995 }
996 } else {
997 std::cerr << __func__ << "unknow type : " << dname << "," << type << std::endl;
998 }
999 return 0;
1000 }