mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
Merge pull request #14258 from liewegas/wip-bluestore-tool
ceph-bluestore-tool: rename from bluefs-tool; improve usage
This commit is contained in:
commit
c618d22d25
@ -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
|
||||
|
2
debian/ceph-osd.install
vendored
2
debian/ceph-osd.install
vendored
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1,96 +0,0 @@
|
||||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
||||
// vim: ts=8 sw=2 smarttab
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#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] << " <outdir> <bdev[0..2]>" << std::endl;;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
vector<const char*> 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<string> dirs;
|
||||
r = fs.readdir("", &dirs);
|
||||
assert(r == 0);
|
||||
for (auto& dir : dirs) {
|
||||
if (dir[0] == '.')
|
||||
continue;
|
||||
cout << dir << "/" << std::endl;
|
||||
vector<string> 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);
|
||||
}
|
||||
}
|
||||
}
|
240
src/os/bluestore/bluestore_tool.cc
Normal file
240
src/os/bluestore/bluestore_tool.cc
Normal file
@ -0,0 +1,240 @@
|
||||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
||||
// vim: ts=8 sw=2 smarttab
|
||||
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#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<string> 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<string>(&path), "bluestore path")
|
||||
("out-dir", po::value<string>(&out_dir), "output directory")
|
||||
("dev", po::value<vector<string>>(&devs), "device(s)")
|
||||
("deep", po::value<bool>(&fsck_deep), "deep fsck (read all data)")
|
||||
;
|
||||
po::options_description po_positional("Positional options");
|
||||
po_positional.add_options()
|
||||
("command", po::value<string>(&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<string> 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<const char*> 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<int> 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<string> dirs;
|
||||
r = fs.readdir("", &dirs);
|
||||
assert(r == 0);
|
||||
for (auto& dir : dirs) {
|
||||
if (dir[0] == '.')
|
||||
continue;
|
||||
cout << dir << "/" << std::endl;
|
||||
vector<string> 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;
|
||||
}
|
@ -2376,7 +2376,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (vm.count("help")) {
|
||||
usage(desc);
|
||||
usage(all);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user