]> git.proxmox.com Git - ceph.git/blame - ceph/src/os/bluestore/bluestore_tool.cc
update sources to v12.1.2
[ceph.git] / ceph / src / os / bluestore / bluestore_tool.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include <boost/program_options/variables_map.hpp>
5#include <boost/program_options/parsers.hpp>
6
7#include <stdio.h>
8#include <string.h>
9#include <iostream>
10#include <time.h>
11#include <fcntl.h>
12#include <unistd.h>
13#include "global/global_init.h"
14#include "common/ceph_argparse.h"
15#include "include/stringify.h"
16#include "common/errno.h"
17
18#include "os/bluestore/BlueFS.h"
19#include "os/bluestore/BlueStore.h"
20
21namespace po = boost::program_options;
22
23void usage(po::options_description &desc)
24{
25 cout << desc << std::endl;
26}
27
c07f9fc5
FG
28void validate_path(CephContext *cct, const string& path, bool bluefs)
29{
30 BlueStore bluestore(cct, path);
31 string type;
32 int r = bluestore.read_meta("type", &type);
33 if (r < 0) {
34 cerr << "failed to load os-type: " << cpp_strerror(r) << std::endl;
35 exit(EXIT_FAILURE);
36 }
37 if (type != "bluestore") {
38 cerr << "expected bluestore, but type is " << type << std::endl;
39 exit(EXIT_FAILURE);
40 }
41 if (!bluefs) {
42 return;
43 }
44
45 string kv_backend;
46 r = bluestore.read_meta("kv_backend", &kv_backend);
47 if (r < 0) {
48 cerr << "failed to load kv_backend: " << cpp_strerror(r) << std::endl;
49 exit(EXIT_FAILURE);
50 }
51 if (kv_backend != "rocksdb") {
52 cerr << "expect kv_backend to be rocksdb, but is " << kv_backend
53 << std::endl;
54 exit(EXIT_FAILURE);
55 }
56 string bluefs_enabled;
57 r = bluestore.read_meta("bluefs", &bluefs_enabled);
58 if (r < 0) {
59 cerr << "failed to load do_bluefs: " << cpp_strerror(r) << std::endl;
60 exit(EXIT_FAILURE);
61 }
62 if (bluefs_enabled != "1") {
63 cerr << "bluefs not enabled for rocksdb" << std::endl;
64 exit(EXIT_FAILURE);
65 }
66}
67
7c673cae
FG
68int main(int argc, char **argv)
69{
70 string out_dir;
71 vector<string> devs;
72 string path;
73 string action;
31f18b77 74 bool fsck_deep = false;
7c673cae
FG
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)")
82 ;
83 po::options_description po_positional("Positional options");
84 po_positional.add_options()
85 ("command", po::value<string>(&action), "fsck, bluefs-export, show-label")
86 ;
87 po::options_description po_all("All options");
88 po_all.add(po_options).add(po_positional);
89 po::positional_options_description pd;
90 pd.add("command", 1);
91
92 vector<string> ceph_option_strings;
93 po::variables_map vm;
94 try {
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);
98 po::notify(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;
c07f9fc5 103 exit(EXIT_FAILURE);
7c673cae
FG
104 }
105
106 if (vm.count("help")) {
107 usage(po_all);
c07f9fc5 108 exit(EXIT_SUCCESS);
7c673cae
FG
109 }
110 if (action.empty()) {
111 cerr << "must specify an action; --help for help" << std::endl;
c07f9fc5 112 exit(EXIT_FAILURE);
7c673cae
FG
113 }
114
115 if (action == "fsck") {
116 if (path.empty()) {
117 cerr << "must specify bluestore path" << std::endl;
c07f9fc5 118 exit(EXIT_FAILURE);
7c673cae
FG
119 }
120 }
c07f9fc5 121 if (action == "show-label") {
7c673cae
FG
122 if (devs.empty() && path.empty()) {
123 cerr << "must specify bluestore path *or* raw device(s)" << std::endl;
c07f9fc5 124 exit(EXIT_FAILURE);
7c673cae
FG
125 }
126 cout << "infering bluefs devices from bluestore path" << std::endl;
127 for (auto fn : {"block", "block.wal", "block.db"}) {
128 string p = path + "/" + fn;
129 struct stat st;
130 if (::stat(p.c_str(), &st) == 0) {
131 devs.push_back(p);
132 }
133 }
134 }
c07f9fc5
FG
135 if (action == "bluefs-export") {
136 if (path.empty()) {
137 cerr << "must specify bluestore path" << std::endl;
138 exit(EXIT_FAILURE);
139 }
140 if (out_dir.empty()) {
141 cerr << "must specify out-dir to export bluefs" << std::endl;
142 exit(EXIT_FAILURE);
143 }
144 cout << "infering bluefs devices from bluestore path" << std::endl;
145 for (auto fn : {"block", "block.wal", "block.db"}) {
146 string p = path + "/" + fn;
147 struct stat st;
148 if (::stat(p.c_str(), &st) == 0) {
149 devs.push_back(p);
150 }
151 }
152 }
7c673cae
FG
153
154 vector<const char*> args;
155 for (auto& i : ceph_option_strings) {
156 args.push_back(i.c_str());
157 }
158 env_to_vec(args);
159
160 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
161 CODE_ENVIRONMENT_UTILITY, 0);
162 common_init_finish(cct.get());
163
164 cout << "action " << action << std::endl;
165
166 if (action == "fsck" ||
167 action == "fsck-deep") {
c07f9fc5 168 validate_path(cct.get(), path, false);
7c673cae
FG
169 BlueStore bluestore(cct.get(), path);
170 int r = bluestore.fsck(fsck_deep);
171 if (r < 0) {
172 cerr << "error from fsck: " << cpp_strerror(r) << std::endl;
c07f9fc5 173 exit(EXIT_FAILURE);
7c673cae
FG
174 }
175 }
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);
182 if (r < 0) {
183 cerr << "unable to read label for " << i << ": "
184 << cpp_strerror(r) << std::endl;
c07f9fc5 185 exit(EXIT_FAILURE);
7c673cae
FG
186 }
187 jf.open_object_section(i.c_str());
188 label.dump(&jf);
189 jf.close_section();
190 }
191 jf.close_section();
192 jf.flush(cout);
193 }
194 else if (action == "bluefs-export") {
c07f9fc5 195 validate_path(cct.get(), path, true);
7c673cae
FG
196 BlueFS fs(&(*cct));
197 string main;
198 set<int> got;
199 for (auto& i : devs) {
200 bluestore_bdev_label_t label;
201 int r = BlueStore::_read_bdev_label(cct.get(), i, &label);
202 if (r < 0) {
203 cerr << "unable to read label for " << i << ": "
204 << cpp_strerror(r) << std::endl;
c07f9fc5 205 exit(EXIT_FAILURE);
7c673cae
FG
206 }
207 int id = -1;
208 if (label.description == "main")
209 main = i;
210 else if (label.description == "bluefs db")
211 id = BlueFS::BDEV_DB;
212 else if (label.description == "bluefs wal")
213 id = BlueFS::BDEV_WAL;
214 if (id >= 0) {
215 got.insert(id);
216 cout << " slot " << id << " " << i << std::endl;
217 int r = fs.add_block_device(id, i);
218 if (r < 0) {
219 cerr << "unable to open " << i << ": " << cpp_strerror(r) << std::endl;
c07f9fc5 220 exit(EXIT_FAILURE);
7c673cae
FG
221 }
222 }
223 }
224 if (main.length()) {
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);
230 if (r < 0) {
231 cerr << "unable to open " << main << ": " << cpp_strerror(r)
232 << std::endl;
c07f9fc5 233 exit(EXIT_FAILURE);
7c673cae
FG
234 }
235 }
236
237 int r = fs.mount();
238 if (r < 0) {
239 cerr << "unable to mount bluefs: " << cpp_strerror(r)
240 << std::endl;
c07f9fc5 241 exit(EXIT_FAILURE);
7c673cae
FG
242 }
243
244 vector<string> dirs;
245 r = fs.readdir("", &dirs);
246 if (r < 0) {
247 cerr << "readdir in root failed: " << cpp_strerror(r) << std::endl;
c07f9fc5 248 exit(EXIT_FAILURE);
7c673cae
FG
249 }
250 for (auto& dir : dirs) {
251 if (dir[0] == '.')
252 continue;
253 cout << dir << "/" << std::endl;
254 vector<string> ls;
255 r = fs.readdir(dir, &ls);
256 if (r < 0) {
257 cerr << "readdir " << dir << " failed: " << cpp_strerror(r) << std::endl;
c07f9fc5 258 exit(EXIT_FAILURE);
7c673cae
FG
259 }
260 string full = out_dir + "/" + dir;
261 r = ::mkdir(full.c_str(), 0755);
262 if (r < 0) {
c07f9fc5 263 r = -errno;
7c673cae 264 cerr << "mkdir " << full << " failed: " << cpp_strerror(r) << std::endl;
c07f9fc5 265 exit(EXIT_FAILURE);
7c673cae
FG
266 }
267 for (auto& file : ls) {
268 if (file[0] == '.')
269 continue;
270 cout << dir << "/" << file << std::endl;
271 uint64_t size;
272 utime_t mtime;
273 r = fs.stat(dir, file, &size, &mtime);
274 if (r < 0) {
275 cerr << "stat " << file << " failed: " << cpp_strerror(r) << std::endl;
c07f9fc5 276 exit(EXIT_FAILURE);
7c673cae
FG
277 }
278 string path = out_dir + "/" + dir + "/" + file;
279 int fd = ::open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644);
280 if (fd < 0) {
281 r = -errno;
282 cerr << "open " << path << " failed: " << cpp_strerror(r) << std::endl;
c07f9fc5 283 exit(EXIT_FAILURE);
7c673cae
FG
284 }
285 assert(fd >= 0);
286 if (size > 0) {
287 BlueFS::FileReader *h;
288 r = fs.open_for_read(dir, file, &h, false);
289 if (r < 0) {
290 cerr << "open_for_read " << dir << "/" << file << " failed: "
291 << cpp_strerror(r) << std::endl;
c07f9fc5 292 exit(EXIT_FAILURE);
7c673cae
FG
293 }
294 int pos = 0;
295 int left = size;
296 while (left) {
297 bufferlist bl;
298 r = fs.read(h, &h->buf, pos, left, &bl, NULL);
299 if (r <= 0) {
300 cerr << "read " << dir << "/" << file << " from " << pos
301 << " failed: " << cpp_strerror(r) << std::endl;
c07f9fc5 302 exit(EXIT_FAILURE);
7c673cae
FG
303 }
304 int rc = bl.write_fd(fd);
305 if (rc < 0) {
306 cerr << "write to " << path << " failed: "
307 << cpp_strerror(r) << std::endl;
c07f9fc5 308 exit(EXIT_FAILURE);
7c673cae
FG
309 }
310 pos += r;
311 left -= r;
312 }
313 delete h;
314 }
315 ::close(fd);
316 }
317 }
318 fs.umount();
319 } else {
320 cerr << "unrecognized action " << action << std::endl;
321 return 1;
322 }
323
324 return 0;
325}