diff --git a/ceph.spec.in b/ceph.spec.in index b2e1c49ea97..152dcf8c2ee 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -1359,7 +1359,7 @@ fi %files osd %{_bindir}/ceph-clsinfo -%{_bindir}/ceph-bluefs-tool +%{_bindir}/ceph-bluestore-tool %{_bindir}/ceph-objectstore-tool %{_bindir}/ceph-osd %{_sbindir}/ceph-disk diff --git a/debian/ceph-osd.install b/debian/ceph-osd.install index 237833bfdea..9f520ec4769 100644 --- a/debian/ceph-osd.install +++ b/debian/ceph-osd.install @@ -4,7 +4,7 @@ usr/sbin/ceph-disk usr/sbin/ceph-disk-udev usr/bin/ceph-clsinfo usr/bin/ceph-objectstore-tool -usr/bin/ceph-bluefs-tool +usr/bin/ceph-bluestore-tool usr/bin/ceph_objectstore_bench usr/bin/ceph-osd usr/lib/ceph/ceph-osd-prestart.sh diff --git a/src/os/CMakeLists.txt b/src/os/CMakeLists.txt index 98defc886dc..93255a3b045 100644 --- a/src/os/CMakeLists.txt +++ b/src/os/CMakeLists.txt @@ -85,11 +85,11 @@ target_link_libraries(os kv) add_dependencies(os compressor_plugins) if(HAVE_LIBAIO) - add_executable(ceph-bluefs-tool - bluestore/bluefs_tool.cc) - target_link_libraries(ceph-bluefs-tool + add_executable(ceph-bluestore-tool + bluestore/bluestore_tool.cc) + target_link_libraries(ceph-bluestore-tool os global) - install(TARGETS ceph-bluefs-tool + install(TARGETS ceph-bluestore-tool DESTINATION bin) endif() diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index 7ced85afd93..c69b48d6790 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/bluefs_tool.cc b/src/os/bluestore/bluefs_tool.cc deleted file mode 100644 index dc7812367b5..00000000000 --- a/src/os/bluestore/bluefs_tool.cc +++ /dev/null @@ -1,96 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include -#include -#include -#include -#include -#include -#include "global/global_init.h" -#include "common/ceph_argparse.h" -#include "include/stringify.h" -#include "common/errno.h" - -#include "os/bluestore/BlueFS.h" - -void usage(char **argv) -{ - cout << argv[0] << " " << std::endl;; -} - -int main(int argc, char **argv) -{ - vector args; - argv_to_vec(argc, (const char **)argv, args); - 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)); - - if (args.size() != 4) { - usage(argv); - 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(); - 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); - assert(r == 0); - string cmd = "mkdir -p " + outdir + "/" + dir; - r = system(cmd.c_str()); - assert(r == 0); - 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); - 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); - 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; - } - ::close(fd); - } - } -} diff --git a/src/os/bluestore/bluestore_tool.cc b/src/os/bluestore/bluestore_tool.cc new file mode 100644 index 00000000000..aa6be877d6b --- /dev/null +++ b/src/os/bluestore/bluestore_tool.cc @@ -0,0 +1,240 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "global/global_init.h" +#include "common/ceph_argparse.h" +#include "include/stringify.h" +#include "common/errno.h" + +#include "os/bluestore/BlueFS.h" +#include "os/bluestore/BlueStore.h" + +namespace po = boost::program_options; + +void usage(po::options_description &desc) +{ + cout << desc << std::endl; +} + +int main(int argc, char **argv) +{ + string out_dir; + vector devs; + string path; + string action; + bool fsck_deep; + po::options_description po_options("Options"); + po_options.add_options() + ("help,h", "produce help message") + ("path", po::value(&path), "bluestore path") + ("out-dir", po::value(&out_dir), "output directory") + ("dev", po::value>(&devs), "device(s)") + ("deep", po::value(&fsck_deep), "deep fsck (read all data)") + ; + po::options_description po_positional("Positional options"); + po_positional.add_options() + ("command", po::value(&action), "fsck, bluefs-export, show-label") + ; + 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 (action == "fsck") { + if (path.empty()) { + cerr << "must specify bluestore path" << std::endl; + exit(1); + } + } + if (action == "bluefs-export" || + action == "show-label") { + if (devs.empty() && path.empty()) { + cerr << "must specify bluestore path *or* raw device(s)" << std::endl; + exit(1); + } + cout << "infering bluefs devices from bluestore path" << std::endl; + for (auto fn : {"block", "block.wal", "block.db"}) { + string p = path + "/" + fn; + struct stat st; + if (::stat(p.c_str(), &st) == 0) { + devs.push_back(p); + } + } + } + + vector 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()); + + cout << "action " << action << std::endl; + + if (action == "fsck" || + action == "fsck-deep") { + BlueStore bluestore(cct.get(), path); + int r = bluestore.fsck(fsck_deep); + if (r < 0) { + cerr << "error from fsck: " << cpp_strerror(r) << std::endl; + return 1; + } + } + else 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); + } + else 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); + } + } + + int r = fs.mount(); + if (r < 0) { + cerr << "unable to mount bluefs: " << cpp_strerror(r) + << std::endl; + exit(1); + } + + 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); + assert(r == 0); + string full = out_dir + "/" + dir; + r = ::mkdir(full.c_str(), 0755); + assert(r == 0); + 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); + 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; + } + ::close(fd); + } + } + fs.umount(); + } else { + cerr << "unrecognized action " << action << std::endl; + return 1; + } + + return 0; +} diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index 0f62313817d..bc72582b82c 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -2376,7 +2376,7 @@ int main(int argc, char **argv) } if (vm.count("help")) { - usage(desc); + usage(all); return 1; }