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 void validate_path(CephContext
*cct
, const string
& path
, bool bluefs
)
30 BlueStore
bluestore(cct
, path
);
32 int r
= bluestore
.read_meta("type", &type
);
34 cerr
<< "failed to load os-type: " << cpp_strerror(r
) << std::endl
;
37 if (type
!= "bluestore") {
38 cerr
<< "expected bluestore, but type is " << type
<< std::endl
;
46 r
= bluestore
.read_meta("kv_backend", &kv_backend
);
48 cerr
<< "failed to load kv_backend: " << cpp_strerror(r
) << std::endl
;
51 if (kv_backend
!= "rocksdb") {
52 cerr
<< "expect kv_backend to be rocksdb, but is " << kv_backend
56 string bluefs_enabled
;
57 r
= bluestore
.read_meta("bluefs", &bluefs_enabled
);
59 cerr
<< "failed to load do_bluefs: " << cpp_strerror(r
) << std::endl
;
62 if (bluefs_enabled
!= "1") {
63 cerr
<< "bluefs not enabled for rocksdb" << std::endl
;
68 int main(int argc
, char **argv
)
74 bool fsck_deep
= false;
75 po::options_description
po_options("Options");
76 po_options
.add_options()
77 ("help,h", "produce help message")
78 ("path", po::value
<string
>(&path
), "bluestore path")
79 ("out-dir", po::value
<string
>(&out_dir
), "output directory")
80 ("dev", po::value
<vector
<string
>>(&devs
), "device(s)")
81 ("deep", po::value
<bool>(&fsck_deep
), "deep fsck (read all data)")
83 po::options_description
po_positional("Positional options");
84 po_positional
.add_options()
85 ("command", po::value
<string
>(&action
), "fsck, bluefs-export, show-label")
87 po::options_description
po_all("All options");
88 po_all
.add(po_options
).add(po_positional
);
89 po::positional_options_description pd
;
92 vector
<string
> ceph_option_strings
;
95 po::parsed_options parsed
=
96 po::command_line_parser(argc
, argv
).options(po_all
).allow_unregistered().positional(pd
).run();
97 po::store( parsed
, vm
);
99 ceph_option_strings
= po::collect_unrecognized(parsed
.options
,
100 po::include_positional
);
101 } catch(po::error
&e
) {
102 std::cerr
<< e
.what() << std::endl
;
106 if (vm
.count("help")) {
110 if (action
.empty()) {
111 cerr
<< "must specify an action; --help for help" << std::endl
;
115 if (action
== "fsck") {
117 cerr
<< "must specify bluestore path" << std::endl
;
121 if (action
== "show-label") {
122 if (devs
.empty() && path
.empty()) {
123 cerr
<< "must specify bluestore path *or* raw device(s)" << std::endl
;
126 cout
<< "infering bluefs devices from bluestore path" << std::endl
;
127 for (auto fn
: {"block", "block.wal", "block.db"}) {
128 string p
= path
+ "/" + fn
;
130 if (::stat(p
.c_str(), &st
) == 0) {
135 if (action
== "bluefs-export") {
137 cerr
<< "must specify bluestore path" << std::endl
;
140 if (out_dir
.empty()) {
141 cerr
<< "must specify out-dir to export bluefs" << std::endl
;
144 cout
<< "infering bluefs devices from bluestore path" << std::endl
;
145 for (auto fn
: {"block", "block.wal", "block.db"}) {
146 string p
= path
+ "/" + fn
;
148 if (::stat(p
.c_str(), &st
) == 0) {
154 vector
<const char*> args
;
155 for (auto& i
: ceph_option_strings
) {
156 args
.push_back(i
.c_str());
160 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
161 CODE_ENVIRONMENT_UTILITY
, 0);
162 common_init_finish(cct
.get());
164 cout
<< "action " << action
<< std::endl
;
166 if (action
== "fsck" ||
167 action
== "fsck-deep") {
168 validate_path(cct
.get(), path
, false);
169 BlueStore
bluestore(cct
.get(), path
);
170 int r
= bluestore
.fsck(fsck_deep
);
172 cerr
<< "error from fsck: " << cpp_strerror(r
) << std::endl
;
176 else if (action
== "show-label") {
177 JSONFormatter
jf(true);
178 jf
.open_array_section("devices");
179 for (auto& i
: devs
) {
180 bluestore_bdev_label_t label
;
181 int r
= BlueStore::_read_bdev_label(cct
.get(), i
, &label
);
183 cerr
<< "unable to read label for " << i
<< ": "
184 << cpp_strerror(r
) << std::endl
;
187 jf
.open_object_section(i
.c_str());
194 else if (action
== "bluefs-export") {
195 validate_path(cct
.get(), path
, true);
199 for (auto& i
: devs
) {
200 bluestore_bdev_label_t label
;
201 int r
= BlueStore::_read_bdev_label(cct
.get(), i
, &label
);
203 cerr
<< "unable to read label for " << i
<< ": "
204 << cpp_strerror(r
) << std::endl
;
208 if (label
.description
== "main")
210 else if (label
.description
== "bluefs db")
211 id
= BlueFS::BDEV_DB
;
212 else if (label
.description
== "bluefs wal")
213 id
= BlueFS::BDEV_WAL
;
216 cout
<< " slot " << id
<< " " << i
<< std::endl
;
217 int r
= fs
.add_block_device(id
, i
);
219 cerr
<< "unable to open " << i
<< ": " << cpp_strerror(r
) << std::endl
;
225 int id
= BlueFS::BDEV_DB
;
226 if (got
.count(BlueFS::BDEV_DB
))
227 id
= BlueFS::BDEV_SLOW
;
228 cout
<< " slot " << id
<< " " << main
<< std::endl
;
229 int r
= fs
.add_block_device(id
, main
);
231 cerr
<< "unable to open " << main
<< ": " << cpp_strerror(r
)
239 cerr
<< "unable to mount bluefs: " << cpp_strerror(r
)
245 r
= fs
.readdir("", &dirs
);
247 cerr
<< "readdir in root failed: " << cpp_strerror(r
) << std::endl
;
250 for (auto& dir
: dirs
) {
253 cout
<< dir
<< "/" << std::endl
;
255 r
= fs
.readdir(dir
, &ls
);
257 cerr
<< "readdir " << dir
<< " failed: " << cpp_strerror(r
) << std::endl
;
260 string full
= out_dir
+ "/" + dir
;
261 r
= ::mkdir(full
.c_str(), 0755);
264 cerr
<< "mkdir " << full
<< " failed: " << cpp_strerror(r
) << std::endl
;
267 for (auto& file
: ls
) {
270 cout
<< dir
<< "/" << file
<< std::endl
;
273 r
= fs
.stat(dir
, file
, &size
, &mtime
);
275 cerr
<< "stat " << file
<< " failed: " << cpp_strerror(r
) << std::endl
;
278 string path
= out_dir
+ "/" + dir
+ "/" + file
;
279 int fd
= ::open(path
.c_str(), O_CREAT
|O_WRONLY
|O_TRUNC
, 0644);
282 cerr
<< "open " << path
<< " failed: " << cpp_strerror(r
) << std::endl
;
287 BlueFS::FileReader
*h
;
288 r
= fs
.open_for_read(dir
, file
, &h
, false);
290 cerr
<< "open_for_read " << dir
<< "/" << file
<< " failed: "
291 << cpp_strerror(r
) << std::endl
;
298 r
= fs
.read(h
, &h
->buf
, pos
, left
, &bl
, NULL
);
300 cerr
<< "read " << dir
<< "/" << file
<< " from " << pos
301 << " failed: " << cpp_strerror(r
) << std::endl
;
304 int rc
= bl
.write_fd(fd
);
306 cerr
<< "write to " << path
<< " failed: "
307 << cpp_strerror(r
) << std::endl
;
320 cerr
<< "unrecognized action " << action
<< std::endl
;