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