From 68354d7406ed22c67779b2bbd6aaf8aaabe1c297 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 30 Mar 2017 15:45:17 -0400 Subject: [PATCH] ceph-bluestore-tool: clean up usage and bluefs-export command Signed-off-by: Sage Weil --- src/os/bluestore/BlueStore.h | 2 + src/os/bluestore/bluestore_tool.cc | 221 ++++++++++++++++++++++------- 2 files changed, 168 insertions(+), 55 deletions(-) diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index fca4e20f2a42..99e7570bb42f 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -1858,8 +1858,10 @@ private: bool create); int _write_bdev_label(string path, bluestore_bdev_label_t label); +public: static int _read_bdev_label(CephContext* cct, string path, bluestore_bdev_label_t *label); +private: int _check_or_set_bdev_label(string path, uint64_t size, string desc, bool create); diff --git a/src/os/bluestore/bluestore_tool.cc b/src/os/bluestore/bluestore_tool.cc index dc7812367b5e..7ae4fd6b1bc8 100644 --- a/src/os/bluestore/bluestore_tool.cc +++ b/src/os/bluestore/bluestore_tool.cc @@ -1,6 +1,9 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include +#include + #include #include #include @@ -13,84 +16,192 @@ #include "common/errno.h" #include "os/bluestore/BlueFS.h" +#include "os/bluestore/BlueStore.h" + +namespace po = boost::program_options; -void usage(char **argv) +void usage(po::options_description &desc) { - cout << argv[0] << " " << std::endl;; + cout << desc << std::endl; } int main(int argc, char **argv) { + string out_dir; + vector devs; + string action; + po::options_description po_options("Options"); + po_options.add_options() + ("help,h", "produce help message") + ("out-dir", po::value(&out_dir), "output directory") + ("dev", po::value>(&devs), "device(s)") + ; + po::options_description po_positional("Positional options"); + po_positional.add_options() + ("command", po::value(&action), "show-label, bluefs-export") + ; + po::options_description po_all("All options"); + po_all.add(po_options).add(po_positional); + po::positional_options_description pd; + pd.add("command", 1); + + vector ceph_option_strings; + po::variables_map vm; + try { + po::parsed_options parsed = + po::command_line_parser(argc, argv).options(po_all).allow_unregistered().positional(pd).run(); + po::store( parsed, vm); + po::notify(vm); + ceph_option_strings = po::collect_unrecognized(parsed.options, + po::include_positional); + } catch(po::error &e) { + std::cerr << e.what() << std::endl; + return 1; + } + + if (vm.count("help")) { + usage(po_all); + return 1; + } + if (action.empty()) { + cerr << "must specify an action; --help for help" << std::endl; + return 1; + } + + if (devs.empty()) { + cerr << "must specify one or more device(s)" << std::endl; + exit(1); + } + vector args; - argv_to_vec(argc, (const char **)argv, args); + for (auto& i : ceph_option_strings) { + args.push_back(i.c_str()); + } env_to_vec(args); auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); common_init_finish(cct.get()); - cct->_conf->set_val( - "enable_experimental_unrecoverable_data_corrupting_features", - "*"); - cct->_conf->apply_changes(NULL); - BlueFS fs(&(*cct)); + cout << "action " << action << std::endl; - if (args.size() != 4) { - usage(argv); - exit(-1); + if (action == "show-label") { + JSONFormatter jf(true); + jf.open_array_section("devices"); + for (auto& i : devs) { + bluestore_bdev_label_t label; + int r = BlueStore::_read_bdev_label(cct.get(), i, &label); + if (r < 0) { + cerr << "unable to read label for " << i << ": " + << cpp_strerror(r) << std::endl; + exit(1); + } + jf.open_object_section(i.c_str()); + label.dump(&jf); + jf.close_section(); + } + jf.close_section(); + jf.flush(cout); } + if (action == "bluefs-export") { + if (out_dir.empty()) { + cerr << "must specify out-dir to export bluefs" << std::endl; + exit(1); + } + BlueFS fs(&(*cct)); + string main; + set got; + for (auto& i : devs) { + bluestore_bdev_label_t label; + int r = BlueStore::_read_bdev_label(cct.get(), i, &label); + if (r < 0) { + cerr << "unable to read label for " << i << ": " + << cpp_strerror(r) << std::endl; + exit(1); + } + int id = -1; + if (label.description == "main") + main = i; + else if (label.description == "bluefs db") + id = BlueFS::BDEV_DB; + else if (label.description == "bluefs wal") + id = BlueFS::BDEV_WAL; + if (id >= 0) { + got.insert(id); + cout << " slot " << id << " " << i << std::endl; + int r = fs.add_block_device(id, i); + if (r < 0) { + cerr << "unable to open " << i << ": " << cpp_strerror(r) << std::endl; + exit(1); + } + } + } + if (main.length()) { + int id = BlueFS::BDEV_DB; + if (got.count(BlueFS::BDEV_DB)) + id = BlueFS::BDEV_SLOW; + cout << " slot " << id << " " << main << std::endl; + int r = fs.add_block_device(id, main); + if (r < 0) { + cerr << "unable to open " << main << ": " << cpp_strerror(r) + << std::endl; + exit(1); + } + } - cout << "args " << args << std::endl; - string outdir = args[0]; - for (unsigned i = 1; i < args.size(); ++i) { - fs.add_block_device(i-1, args[i]); - } + int r = fs.mount(); + if (r < 0) { + cerr << "unable to mount bluefs: " << cpp_strerror(r) + << std::endl; + exit(1); + } - int r = fs.mount(); - assert(r == 0); - - vector dirs; - r = fs.readdir("", &dirs); - assert(r == 0); - for (auto& dir : dirs) { - if (dir[0] == '.') - continue; - cout << dir << "/" << std::endl; - vector ls; - r = fs.readdir(dir, &ls); + vector dirs; + r = fs.readdir("", &dirs); assert(r == 0); - string cmd = "mkdir -p " + outdir + "/" + dir; - r = system(cmd.c_str()); - assert(r == 0); - for (auto& file : ls) { - if (file[0] == '.') + for (auto& dir : dirs) { + if (dir[0] == '.') continue; - cout << dir << "/" << file << std::endl; - uint64_t size; - utime_t mtime; - r = fs.stat(dir, file, &size, &mtime); + cout << dir << "/" << std::endl; + vector ls; + r = fs.readdir(dir, &ls); + assert(r == 0); + string full = out_dir + "/" + dir; + r = ::mkdir(full.c_str(), 0755); assert(r == 0); - string path = outdir + "/" + dir + "/" + file; - int fd = ::open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644); - assert(fd >= 0); - if (size > 0) { - BlueFS::FileReader *h; - r = fs.open_for_read(dir, file, &h, false); + for (auto& file : ls) { + if (file[0] == '.') + continue; + cout << dir << "/" << file << std::endl; + uint64_t size; + utime_t mtime; + r = fs.stat(dir, file, &size, &mtime); assert(r == 0); - int pos = 0; - int left = size; - while (left) { - bufferlist bl; - r = fs.read(h, &h->buf, pos, left, &bl, NULL); - assert(r > 0); - int rc = bl.write_fd(fd); - assert(rc == 0); - pos += r; - left -= r; + string path = out_dir + "/" + dir + "/" + file; + int fd = ::open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644); + assert(fd >= 0); + if (size > 0) { + BlueFS::FileReader *h; + r = fs.open_for_read(dir, file, &h, false); + assert(r == 0); + int pos = 0; + int left = size; + while (left) { + bufferlist bl; + r = fs.read(h, &h->buf, pos, left, &bl, NULL); + assert(r > 0); + int rc = bl.write_fd(fd); + assert(rc == 0); + pos += r; + left -= r; + } + delete h; } - delete h; + ::close(fd); } - ::close(fd); } + fs.umount(); } + + return 0; } -- 2.47.3