1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include <boost/program_options/variables_map.hpp>
5 #include <boost/program_options/parsers.hpp>
13 #include "global/global_init.h"
14 #include "common/ceph_argparse.h"
15 #include "include/stringify.h"
16 #include "common/errno.h"
18 #include "os/bluestore/BlueFS.h"
19 #include "os/bluestore/BlueStore.h"
21 namespace po
= boost::program_options
;
23 void usage(po::options_description
&desc
)
25 cout
<< desc
<< std::endl
;
28 int main(int argc
, char **argv
)
35 po::options_description
po_options("Options");
36 po_options
.add_options()
37 ("help,h", "produce help message")
38 ("path", po::value
<string
>(&path
), "bluestore path")
39 ("out-dir", po::value
<string
>(&out_dir
), "output directory")
40 ("dev", po::value
<vector
<string
>>(&devs
), "device(s)")
41 ("deep", po::value
<bool>(&fsck_deep
), "deep fsck (read all data)")
43 po::options_description
po_positional("Positional options");
44 po_positional
.add_options()
45 ("command", po::value
<string
>(&action
), "fsck, bluefs-export, show-label")
47 po::options_description
po_all("All options");
48 po_all
.add(po_options
).add(po_positional
);
49 po::positional_options_description pd
;
52 vector
<string
> ceph_option_strings
;
55 po::parsed_options parsed
=
56 po::command_line_parser(argc
, argv
).options(po_all
).allow_unregistered().positional(pd
).run();
57 po::store( parsed
, vm
);
59 ceph_option_strings
= po::collect_unrecognized(parsed
.options
,
60 po::include_positional
);
61 } catch(po::error
&e
) {
62 std::cerr
<< e
.what() << std::endl
;
66 if (vm
.count("help")) {
71 cerr
<< "must specify an action; --help for help" << std::endl
;
75 if (action
== "fsck") {
77 cerr
<< "must specify bluestore path" << std::endl
;
81 if (action
== "bluefs-export" ||
82 action
== "show-label") {
83 if (devs
.empty() && path
.empty()) {
84 cerr
<< "must specify bluestore path *or* raw device(s)" << std::endl
;
87 cout
<< "infering bluefs devices from bluestore path" << std::endl
;
88 for (auto fn
: {"block", "block.wal", "block.db"}) {
89 string p
= path
+ "/" + fn
;
91 if (::stat(p
.c_str(), &st
) == 0) {
97 vector
<const char*> args
;
98 for (auto& i
: ceph_option_strings
) {
99 args
.push_back(i
.c_str());
103 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
104 CODE_ENVIRONMENT_UTILITY
, 0);
105 common_init_finish(cct
.get());
107 cout
<< "action " << action
<< std::endl
;
109 if (action
== "fsck" ||
110 action
== "fsck-deep") {
111 BlueStore
bluestore(cct
.get(), path
);
112 int r
= bluestore
.fsck(fsck_deep
);
114 cerr
<< "error from fsck: " << cpp_strerror(r
) << std::endl
;
118 else if (action
== "show-label") {
119 JSONFormatter
jf(true);
120 jf
.open_array_section("devices");
121 for (auto& i
: devs
) {
122 bluestore_bdev_label_t label
;
123 int r
= BlueStore::_read_bdev_label(cct
.get(), i
, &label
);
125 cerr
<< "unable to read label for " << i
<< ": "
126 << cpp_strerror(r
) << std::endl
;
129 jf
.open_object_section(i
.c_str());
136 else if (action
== "bluefs-export") {
137 if (out_dir
.empty()) {
138 cerr
<< "must specify out-dir to export bluefs" << std::endl
;
144 for (auto& i
: devs
) {
145 bluestore_bdev_label_t label
;
146 int r
= BlueStore::_read_bdev_label(cct
.get(), i
, &label
);
148 cerr
<< "unable to read label for " << i
<< ": "
149 << cpp_strerror(r
) << std::endl
;
153 if (label
.description
== "main")
155 else if (label
.description
== "bluefs db")
156 id
= BlueFS::BDEV_DB
;
157 else if (label
.description
== "bluefs wal")
158 id
= BlueFS::BDEV_WAL
;
161 cout
<< " slot " << id
<< " " << i
<< std::endl
;
162 int r
= fs
.add_block_device(id
, i
);
164 cerr
<< "unable to open " << i
<< ": " << cpp_strerror(r
) << std::endl
;
170 int id
= BlueFS::BDEV_DB
;
171 if (got
.count(BlueFS::BDEV_DB
))
172 id
= BlueFS::BDEV_SLOW
;
173 cout
<< " slot " << id
<< " " << main
<< std::endl
;
174 int r
= fs
.add_block_device(id
, main
);
176 cerr
<< "unable to open " << main
<< ": " << cpp_strerror(r
)
184 cerr
<< "unable to mount bluefs: " << cpp_strerror(r
)
190 r
= fs
.readdir("", &dirs
);
192 cerr
<< "readdir in root failed: " << cpp_strerror(r
) << std::endl
;
195 for (auto& dir
: dirs
) {
198 cout
<< dir
<< "/" << std::endl
;
200 r
= fs
.readdir(dir
, &ls
);
202 cerr
<< "readdir " << dir
<< " failed: " << cpp_strerror(r
) << std::endl
;
205 string full
= out_dir
+ "/" + dir
;
206 r
= ::mkdir(full
.c_str(), 0755);
208 cerr
<< "mkdir " << full
<< " failed: " << cpp_strerror(r
) << std::endl
;
211 for (auto& file
: ls
) {
214 cout
<< dir
<< "/" << file
<< std::endl
;
217 r
= fs
.stat(dir
, file
, &size
, &mtime
);
219 cerr
<< "stat " << file
<< " failed: " << cpp_strerror(r
) << std::endl
;
222 string path
= out_dir
+ "/" + dir
+ "/" + file
;
223 int fd
= ::open(path
.c_str(), O_CREAT
|O_WRONLY
|O_TRUNC
, 0644);
226 cerr
<< "open " << path
<< " failed: " << cpp_strerror(r
) << std::endl
;
231 BlueFS::FileReader
*h
;
232 r
= fs
.open_for_read(dir
, file
, &h
, false);
234 cerr
<< "open_for_read " << dir
<< "/" << file
<< " failed: "
235 << cpp_strerror(r
) << std::endl
;
242 r
= fs
.read(h
, &h
->buf
, pos
, left
, &bl
, NULL
);
244 cerr
<< "read " << dir
<< "/" << file
<< " from " << pos
245 << " failed: " << cpp_strerror(r
) << std::endl
;
248 int rc
= bl
.write_fd(fd
);
250 cerr
<< "write to " << path
<< " failed: "
251 << cpp_strerror(r
) << std::endl
;
264 cerr
<< "unrecognized action " << action
<< std::endl
;