summaryrefslogtreecommitdiffstats
path: root/src/tools/cephfs
diff options
context:
space:
mode:
authorJohn Spray <john.spray@redhat.com>2016-02-17 15:57:17 +0100
committerJohn Spray <john.spray@redhat.com>2016-03-10 13:11:23 +0100
commit0ed5eb7a8e31448979c0725aa49fe35ca38a5f29 (patch)
tree867c1094792ec360a5170864a00532c540ab853d /src/tools/cephfs
parentmon: update for multiple filesystems (diff)
downloadceph-0ed5eb7a8e31448979c0725aa49fe35ca38a5f29.tar.xz
ceph-0ed5eb7a8e31448979c0725aa49fe35ca38a5f29.zip
tools/cephfs: update for FSMap
Everywhere we used to take a rank, we now take a role (<fscid:rank>) Signed-off-by: John Spray <john.spray@redhat.com>
Diffstat (limited to 'src/tools/cephfs')
-rw-r--r--src/tools/cephfs/DataScan.cc48
-rw-r--r--src/tools/cephfs/DataScan.h20
-rw-r--r--src/tools/cephfs/Dumper.cc26
-rw-r--r--src/tools/cephfs/Dumper.h8
-rw-r--r--src/tools/cephfs/JournalTool.cc68
-rw-r--r--src/tools/cephfs/JournalTool.h6
-rw-r--r--src/tools/cephfs/MDSUtility.cc18
-rw-r--r--src/tools/cephfs/MDSUtility.h8
-rw-r--r--src/tools/cephfs/Resetter.cc27
-rw-r--r--src/tools/cephfs/Resetter.h4
-rw-r--r--src/tools/cephfs/RoleSelector.cc58
-rw-r--r--src/tools/cephfs/RoleSelector.h35
-rw-r--r--src/tools/cephfs/TableTool.cc122
-rw-r--r--src/tools/cephfs/TableTool.h9
14 files changed, 311 insertions, 146 deletions
diff --git a/src/tools/cephfs/DataScan.cc b/src/tools/cephfs/DataScan.cc
index 0cf2bddbeac..dc70ae6a687 100644
--- a/src/tools/cephfs/DataScan.cc
+++ b/src/tools/cephfs/DataScan.cc
@@ -36,7 +36,7 @@ void DataScan::usage()
<< "\n"
<< " --force-corrupt: overrite apparently corrupt structures\n"
<< " --force-init: write root inodes even if they exist\n"
- << " --force-pool: use data pool even if it is not in MDSMap\n"
+ << " --force-pool: use data pool even if it is not in FSMap\n"
<< "\n"
<< " cephfs-data-scan scan_frags [--force-corrupt]\n"
<< "\n"
@@ -89,6 +89,15 @@ bool DataScan::parse_kwarg(
filter_tag = val;
dout(10) << "Applying tag filter: '" << filter_tag << "'" << dendl;
return true;
+ } else if (arg == std::string("--filesystem")) {
+ std::shared_ptr<Filesystem> fs;
+ *r = fsmap->parse_filesystem(val, &fs);
+ if (*r != 0) {
+ std::cerr << "Invalid filesystem '" << val << "'" << std::endl;
+ return false;
+ }
+ fscid = fs->fscid;
+ return true;
} else {
return false;
}
@@ -168,6 +177,19 @@ int DataScan::main(const std::vector<const char*> &args)
return -EINVAL;
}
+ // If caller didn't specify a namespace, try to pick
+ // one if only one exists
+ if (fscid == FS_CLUSTER_ID_NONE) {
+ if (fsmap->get_filesystems().size() == 1) {
+ fscid = fsmap->get_filesystems().begin()->first;
+ } else {
+ std::cerr << "Specify a filesystem with --filesystem" << std::endl;
+ return -EINVAL;
+ }
+ }
+ auto fs = fsmap->get_filesystem(fscid);
+ assert(fs != nullptr);
+
// Default to output to metadata pool
if (driver == NULL) {
driver = new MetadataDriver();
@@ -178,7 +200,7 @@ int DataScan::main(const std::vector<const char*> &args)
dout(4) << "connecting to RADOS..." << dendl;
rados.connect();
- r = driver->init(rados, mdsmap);
+ r = driver->init(rados, fsmap, fscid);
if (r < 0) {
return r;
}
@@ -201,7 +223,7 @@ int DataScan::main(const std::vector<const char*> &args)
<< "' has ID " << data_pool_id << dendl;
}
- if (!mdsmap->is_data_pool(data_pool_id)) {
+ if (!fs->mds_map.is_data_pool(data_pool_id)) {
std::cerr << "Warning: pool '" << data_pool_name << "' is not a "
"CephFS data pool!" << std::endl;
if (!force_pool) {
@@ -219,7 +241,13 @@ int DataScan::main(const std::vector<const char*> &args)
// Initialize metadata_io from MDSMap for scan_frags
if (command == "scan_frags") {
- int const metadata_pool_id = mdsmap->get_metadata_pool();
+ const auto fs = fsmap->get_filesystem(fscid);
+ if (fs == nullptr) {
+ std::cerr << "Filesystem id " << fscid << " does not exist" << std::endl;
+ return -ENOENT;
+ }
+ int const metadata_pool_id = fs->mds_map.get_metadata_pool();
+
dout(4) << "resolving metadata pool " << metadata_pool_id << dendl;
std::string metadata_pool_name;
int r = rados.pool_reverse_lookup(metadata_pool_id, &metadata_pool_name);
@@ -269,7 +297,7 @@ int DataScan::main(const std::vector<const char*> &args)
} else if (command == "tmap_upgrade") {
return tmap_upgrade();
} else if (command == "init") {
- return driver->init_roots(mdsmap->get_first_data_pool());
+ return driver->init_roots(fs->mds_map.get_first_data_pool());
} else {
std::cerr << "Unknown command '" << command << "'" << std::endl;
return -EINVAL;
@@ -1533,9 +1561,12 @@ int MetadataDriver::inject_linkage(
}
-int MetadataDriver::init(librados::Rados &rados, const MDSMap *mdsmap)
+int MetadataDriver::init(
+ librados::Rados &rados, const FSMap *fsmap, fs_cluster_id_t fscid)
{
- int const metadata_pool_id = mdsmap->get_metadata_pool();
+ auto fs = fsmap->get_filesystem(fscid);
+ assert(fs != nullptr);
+ int const metadata_pool_id = fs->mds_map.get_metadata_pool();
dout(4) << "resolving metadata pool " << metadata_pool_id << dendl;
std::string metadata_pool_name;
@@ -1549,7 +1580,8 @@ int MetadataDriver::init(librados::Rados &rados, const MDSMap *mdsmap)
return rados.ioctx_create(metadata_pool_name.c_str(), metadata_io);
}
-int LocalFileDriver::init(librados::Rados &rados, const MDSMap *mdsmap)
+int LocalFileDriver::init(
+ librados::Rados &rados, const FSMap *fsmap, fs_cluster_id_t fscid)
{
return 0;
}
diff --git a/src/tools/cephfs/DataScan.h b/src/tools/cephfs/DataScan.h
index 3b94063f8ae..107ab7462ff 100644
--- a/src/tools/cephfs/DataScan.h
+++ b/src/tools/cephfs/DataScan.h
@@ -28,7 +28,10 @@ class RecoveryDriver {
bool force_init;
public:
- virtual int init(librados::Rados &rados, const MDSMap *mdsmap) = 0;
+ virtual int init(
+ librados::Rados &rados,
+ const FSMap *fsmap,
+ fs_cluster_id_t fscid) = 0;
void set_force_corrupt(const bool val)
{
@@ -112,7 +115,10 @@ class LocalFileDriver : public RecoveryDriver
{}
// Implement RecoveryDriver interface
- int init(librados::Rados &rados, const MDSMap *mdsmap);
+ int init(
+ librados::Rados &rados,
+ const FSMap *fsmap,
+ fs_cluster_id_t fscid);
int inject_with_backtrace(
const inode_backtrace_t &bt,
@@ -205,7 +211,10 @@ class MetadataDriver : public RecoveryDriver, public MetadataTool
public:
// Implement RecoveryDriver interface
- int init(librados::Rados &rados, const MDSMap *mdsmap);
+ int init(
+ librados::Rados &rados,
+ const FSMap *fsmap,
+ fs_cluster_id_t fscid);
int inject_with_backtrace(
const inode_backtrace_t &bt,
@@ -224,6 +233,7 @@ class DataScan : public MDSUtility, public MetadataTool
{
protected:
RecoveryDriver *driver;
+ fs_cluster_id_t fscid;
// IoCtx for data pool (where we scrape file backtraces from)
librados::IoCtx data_io;
@@ -259,7 +269,7 @@ class DataScan : public MDSUtility, public MetadataTool
*/
int tmap_upgrade();
- // Accept pools which are not in the MDSMap
+ // Accept pools which are not in the FSMap
bool force_pool;
// Respond to decode errors by overwriting
bool force_corrupt;
@@ -301,7 +311,7 @@ class DataScan : public MDSUtility, public MetadataTool
int main(const std::vector<const char *> &args);
DataScan()
- : driver(NULL), data_pool_id(-1), n(0), m(1),
+ : driver(NULL), fscid(FS_CLUSTER_ID_NONE), data_pool_id(-1), n(0), m(1),
force_pool(false), force_corrupt(false),
force_init(false)
{
diff --git a/src/tools/cephfs/Dumper.cc b/src/tools/cephfs/Dumper.cc
index 3344b0daf6d..af04bf61699 100644
--- a/src/tools/cephfs/Dumper.cc
+++ b/src/tools/cephfs/Dumper.cc
@@ -32,16 +32,19 @@
#define HEADER_LEN 4096
-int Dumper::init(int rank_)
+int Dumper::init(mds_role_t role_)
{
- rank = rank_;
+ role = role_;
int r = MDSUtility::init();
if (r < 0) {
return r;
}
- JournalPointer jp(rank, mdsmap->get_metadata_pool());
+ auto fs = fsmap->get_filesystem(role.fscid);
+ assert(fs != nullptr);
+
+ JournalPointer jp(role.rank, fs->mds_map.get_metadata_pool());
int jp_load_result = jp.load(objecter);
if (jp_load_result != 0) {
std::cerr << "Error loading journal: " << cpp_strerror(jp_load_result) << std::endl;
@@ -75,8 +78,12 @@ int Dumper::dump(const char *dump_file)
{
int r = 0;
- Journaler journaler(ino, mdsmap->get_metadata_pool(), CEPH_FS_ONDISK_MAGIC,
- objecter, 0, 0, &timer, &finisher);
+ auto fs = fsmap->get_filesystem(role.fscid);
+ assert(fs != nullptr);
+
+ Journaler journaler(ino, fs->mds_map.get_metadata_pool(),
+ CEPH_FS_ONDISK_MAGIC, objecter, 0, 0,
+ &timer, &finisher);
r = recover_journal(&journaler);
if (r) {
return r;
@@ -95,7 +102,7 @@ int Dumper::dump(const char *dump_file)
char buf[HEADER_LEN];
memset(buf, 0, sizeof(buf));
snprintf(buf, HEADER_LEN, "Ceph mds%d journal dump\n start offset %llu (0x%llx)\n length %llu (0x%llx)\n write_pos %llu (0x%llx)\n format %llu\n trimmed_pos %llu (0x%llx)\n%c",
- rank,
+ role.rank,
(unsigned long long)start, (unsigned long long)start,
(unsigned long long)len, (unsigned long long)len,
(unsigned long long)journaler.last_committed.write_pos, (unsigned long long)journaler.last_committed.write_pos,
@@ -175,6 +182,9 @@ int Dumper::undump(const char *dump_file)
{
cout << "undump " << dump_file << std::endl;
+ auto fs = fsmap->get_filesystem(role.fscid);
+ assert(fs != nullptr);
+
int r = 0;
int fd = ::open(dump_file, O_RDONLY);
if (fd < 0) {
@@ -235,13 +245,13 @@ int Dumper::undump(const char *dump_file)
h.magic = CEPH_FS_ONDISK_MAGIC;
h.layout = file_layout_t::get_default();
- h.layout.pool_id = mdsmap->get_metadata_pool();
+ h.layout.pool_id = fs->mds_map.get_metadata_pool();
bufferlist hbl;
::encode(h, hbl);
object_t oid = file_object_t(ino, 0);
- object_locator_t oloc(mdsmap->get_metadata_pool());
+ object_locator_t oloc(fs->mds_map.get_metadata_pool());
SnapContext snapc;
cout << "writing header " << oid << std::endl;
diff --git a/src/tools/cephfs/Dumper.h b/src/tools/cephfs/Dumper.h
index e94c5960eb1..97b56a7751e 100644
--- a/src/tools/cephfs/Dumper.h
+++ b/src/tools/cephfs/Dumper.h
@@ -29,16 +29,16 @@ class Journaler;
class Dumper : public MDSUtility {
private:
- int rank;
+ mds_role_t role;
inodeno_t ino;
public:
- Dumper() : rank(-1), ino(-1)
+ Dumper() : ino(-1)
{}
- void handle_mds_map(MMDSMap* m);
+ void handle_mds_map(MFSMap* m);
- int init(int rank);
+ int init(mds_role_t role_);
int recover_journal(Journaler *journaler);
int dump(const char *dumpfile);
int undump(const char *dumpfile);
diff --git a/src/tools/cephfs/JournalTool.cc b/src/tools/cephfs/JournalTool.cc
index 4be47b2b239..63e5ac11089 100644
--- a/src/tools/cephfs/JournalTool.cc
+++ b/src/tools/cephfs/JournalTool.cc
@@ -60,7 +60,7 @@ void JournalTool::usage()
<< " <output>: [summary|binary|json] [--path <path>]\n"
<< "\n"
<< "Options:\n"
- << " --rank=<int> Journal rank (default 0)\n";
+ << " --rank=<str> Journal rank (default 0)\n";
generic_client_usage();
}
@@ -82,14 +82,17 @@ int JournalTool::main(std::vector<const char*> &argv)
}
std::vector<const char*>::iterator arg = argv.begin();
+
std::string rank_str;
- if(ceph_argparse_witharg(argv, arg, &rank_str, "--rank", (char*)NULL)) {
- std::string rank_err;
- rank = strict_strtol(rank_str.c_str(), 10, &rank_err);
- if (!rank_err.empty()) {
- derr << "Bad rank '" << rank_str << "'" << dendl;
- usage();
- }
+ if(!ceph_argparse_witharg(argv, arg, &rank_str, "--rank", (char*)NULL)) {
+ // Default: act on rank 0. Will give the user an error if they
+ // try invoking this way when they have more than one filesystem.
+ rank_str = "0";
+ }
+
+ r = role_selector.parse(*fsmap, rank_str);
+ if (r != 0) {
+ return r;
}
std::string mode;
@@ -111,7 +114,9 @@ int JournalTool::main(std::vector<const char*> &argv)
dout(4) << "JournalTool: connecting to RADOS..." << dendl;
rados.connect();
- int const pool_id = mdsmap->get_metadata_pool();
+ auto fs = fsmap->get_filesystem(role_selector.get_ns());
+ assert(fs != nullptr);
+ int const pool_id = fs->mds_map.get_metadata_pool();
dout(4) << "JournalTool: resolving pool " << pool_id << dendl;
std::string pool_name;
r = rados.pool_reverse_lookup(pool_id, &pool_name);
@@ -126,18 +131,27 @@ int JournalTool::main(std::vector<const char*> &argv)
// Execution
// =========
- dout(4) << "Executing for rank " << rank << dendl;
- if (mode == std::string("journal")) {
- return main_journal(argv);
- } else if (mode == std::string("header")) {
- return main_header(argv);
- } else if (mode == std::string("event")) {
- return main_event(argv);
- } else {
- derr << "Bad command '" << mode << "'" << dendl;
- usage();
- return -EINVAL;
+ for (auto role : role_selector.get_roles()) {
+ rank = role.rank;
+ dout(4) << "Executing for rank " << rank << dendl;
+ if (mode == std::string("journal")) {
+ r = main_journal(argv);
+ } else if (mode == std::string("header")) {
+ r = main_header(argv);
+ } else if (mode == std::string("event")) {
+ r = main_event(argv);
+ } else {
+ derr << "Bad command '" << mode << "'" << dendl;
+ usage();
+ return -EINVAL;
+ }
+
+ if (r != 0) {
+ return r;
+ }
}
+
+ return r;
}
@@ -528,7 +542,7 @@ int JournalTool::journal_export(std::string const &path, bool import)
*/
{
Dumper dumper;
- r = dumper.init(rank);
+ r = dumper.init(mds_role_t(role_selector.get_ns(), rank));
if (r < 0) {
derr << "dumper::init failed: " << cpp_strerror(r) << dendl;
return r;
@@ -558,15 +572,10 @@ int JournalTool::journal_reset(bool hard)
return r;
}
- if (mdsmap->is_dne(mds_rank_t(rank))) {
- std::cerr << "MDS rank " << rank << " does not exist" << std::endl;
- return -ENOENT;
- }
-
if (hard) {
- r = resetter.reset_hard(rank);
+ r = resetter.reset_hard(mds_role_t(role_selector.get_ns(), rank));
} else {
- r = resetter.reset(rank);
+ r = resetter.reset(mds_role_t(role_selector.get_ns(), rank));
}
resetter.shutdown();
@@ -1209,8 +1218,9 @@ int JournalTool::consume_inos(const std::set<inodeno_t> &inos)
int r = 0;
// InoTable is a per-MDS structure, so iterate over assigned ranks
+ auto fs = fsmap->get_filesystem(role_selector.get_ns());
std::set<mds_rank_t> in_ranks;
- mdsmap->get_mds_set(in_ranks);
+ fs->mds_map.get_mds_set(in_ranks);
for (std::set<mds_rank_t>::iterator rank_i = in_ranks.begin();
rank_i != in_ranks.end(); ++rank_i)
diff --git a/src/tools/cephfs/JournalTool.h b/src/tools/cephfs/JournalTool.h
index f717859a6f1..f8f90606fd0 100644
--- a/src/tools/cephfs/JournalTool.h
+++ b/src/tools/cephfs/JournalTool.h
@@ -12,6 +12,7 @@
*/
#include "MDSUtility.h"
+#include "RoleSelector.h"
#include <vector>
#include "mds/mdstypes.h"
@@ -32,7 +33,10 @@ class JournalScanner;
class JournalTool : public MDSUtility
{
private:
- int rank;
+ MDSRoleSelector role_selector;
+ // Bit hacky, use this `rank` member to control behaviour of the
+ // various main_ functions.
+ mds_rank_t rank;
// Entry points
int main_journal(std::vector<const char*> &argv);
diff --git a/src/tools/cephfs/MDSUtility.cc b/src/tools/cephfs/MDSUtility.cc
index d335d92fda0..b6b9eab1441 100644
--- a/src/tools/cephfs/MDSUtility.cc
+++ b/src/tools/cephfs/MDSUtility.cc
@@ -27,7 +27,7 @@ MDSUtility::MDSUtility() :
{
monc = new MonClient(g_ceph_context);
messenger = Messenger::create_client_messenger(g_ceph_context, "mds");
- mdsmap = new MDSMap();
+ fsmap = new FSMap();
objecter = new Objecter(g_ceph_context, messenger, monc, NULL, 0, 0);
}
@@ -37,7 +37,7 @@ MDSUtility::~MDSUtility()
delete objecter;
delete monc;
delete messenger;
- delete mdsmap;
+ delete fsmap;
assert(waiting_for_mds_map == NULL);
}
@@ -91,11 +91,11 @@ int MDSUtility::init()
Mutex init_lock("MDSUtility:init");
Cond cond;
bool done = false;
- assert(!mdsmap->get_epoch());
+ assert(!fsmap->get_epoch());
lock.Lock();
waiting_for_mds_map = new C_SafeCond(&init_lock, &cond, &done, NULL);
lock.Unlock();
- monc->sub_want("mdsmap", 0, CEPH_SUBSCRIBE_ONETIME);
+ monc->sub_want("fsmap", 0, CEPH_SUBSCRIBE_ONETIME);
monc->renew_subs();
// Wait for MDS map
@@ -104,7 +104,7 @@ int MDSUtility::init()
while (!done)
cond.Wait(init_lock);
init_lock.Unlock();
- dout(4) << "Got MDS map " << mdsmap->get_epoch() << dendl;
+ dout(4) << "Got MDS map " << fsmap->get_epoch() << dendl;
finisher.start();
@@ -130,8 +130,8 @@ bool MDSUtility::ms_dispatch(Message *m)
{
Mutex::Locker locker(lock);
switch (m->get_type()) {
- case CEPH_MSG_MDS_MAP:
- handle_mds_map((MMDSMap*)m);
+ case CEPH_MSG_FS_MAP:
+ handle_mds_map((MFSMap*)m);
break;
case CEPH_MSG_OSD_MAP:
break;
@@ -142,9 +142,9 @@ bool MDSUtility::ms_dispatch(Message *m)
}
-void MDSUtility::handle_mds_map(MMDSMap* m)
+void MDSUtility::handle_mds_map(MFSMap* m)
{
- mdsmap->decode(m->get_encoded());
+ fsmap->decode(m->get_encoded());
if (waiting_for_mds_map) {
waiting_for_mds_map->complete(0);
waiting_for_mds_map = NULL;
diff --git a/src/tools/cephfs/MDSUtility.h b/src/tools/cephfs/MDSUtility.h
index 4034043a78f..4d233c9b730 100644
--- a/src/tools/cephfs/MDSUtility.h
+++ b/src/tools/cephfs/MDSUtility.h
@@ -15,8 +15,8 @@
#define MDS_UTILITY_H_
#include "osdc/Objecter.h"
-#include "mds/MDSMap.h"
-#include "messages/MMDSMap.h"
+#include "mds/FSMap.h"
+#include "messages/MFSMap.h"
#include "msg/Dispatcher.h"
#include "msg/Messenger.h"
#include "auth/Auth.h"
@@ -32,7 +32,7 @@
class MDSUtility : public Dispatcher {
protected:
Objecter *objecter;
- MDSMap *mdsmap;
+ FSMap *fsmap;
Messenger *messenger;
MonClient *monc;
@@ -46,7 +46,7 @@ public:
MDSUtility();
~MDSUtility();
- void handle_mds_map(MMDSMap* m);
+ void handle_mds_map(MFSMap* m);
bool ms_dispatch(Message *m);
bool ms_handle_reset(Connection *con) { return false; }
void ms_handle_remote_reset(Connection *con) {}
diff --git a/src/tools/cephfs/Resetter.cc b/src/tools/cephfs/Resetter.cc
index b255f9ee7bb..f1102f35a48 100644
--- a/src/tools/cephfs/Resetter.cc
+++ b/src/tools/cephfs/Resetter.cc
@@ -25,14 +25,18 @@
#define dout_subsys ceph_subsys_mds
-int Resetter::reset(int rank)
+int Resetter::reset(mds_role_t role)
{
Mutex mylock("Resetter::reset::lock");
Cond cond;
bool done;
int r;
- JournalPointer jp(rank, mdsmap->get_metadata_pool());
+ auto fs = fsmap->get_filesystem(role.fscid);
+ assert(fs != nullptr);
+ int const pool_id = fs->mds_map.get_metadata_pool();
+
+ JournalPointer jp(role.rank, pool_id);
int jp_load_result = jp.load(objecter);
if (jp_load_result != 0) {
std::cerr << "Error loading journal: " << cpp_strerror(jp_load_result) <<
@@ -41,7 +45,7 @@ int Resetter::reset(int rank)
}
Journaler journaler(jp.front,
- mdsmap->get_metadata_pool(),
+ pool_id,
CEPH_FS_ONDISK_MAGIC,
objecter, 0, 0, &timer, &finisher);
@@ -109,10 +113,14 @@ int Resetter::reset(int rank)
return 0;
}
-int Resetter::reset_hard(int rank)
+int Resetter::reset_hard(mds_role_t role)
{
- JournalPointer jp(rank, mdsmap->get_metadata_pool());
- jp.front = rank + MDS_INO_LOG_OFFSET;
+ auto fs = fsmap->get_filesystem(role.fscid);
+ assert(fs != nullptr);
+ int const pool_id = fs->mds_map.get_metadata_pool();
+
+ JournalPointer jp(role.rank, pool_id);
+ jp.front = role.rank + MDS_INO_LOG_OFFSET;
jp.back = 0;
int r = jp.save(objecter);
if (r != 0) {
@@ -121,12 +129,13 @@ int Resetter::reset_hard(int rank)
}
Journaler journaler(jp.front,
- mdsmap->get_metadata_pool(),
+ pool_id,
CEPH_FS_ONDISK_MAGIC,
objecter, 0, 0, &timer, &finisher);
journaler.set_writeable();
- file_layout_t default_log_layout = MDCache::gen_default_log_layout(*mdsmap);
+ file_layout_t default_log_layout = MDCache::gen_default_log_layout(
+ fsmap->get_filesystem(role.fscid)->mds_map);
journaler.create(&default_log_layout, g_conf->mds_journal_format);
C_SaferCond cond;
@@ -150,7 +159,7 @@ int Resetter::reset_hard(int rank)
}
dout(4) << "Successfully wrote new journal pointer and header for rank "
- << rank << dendl;
+ << role << dendl;
return 0;
}
diff --git a/src/tools/cephfs/Resetter.h b/src/tools/cephfs/Resetter.h
index 2baaf47f43a..115f6ffeecb 100644
--- a/src/tools/cephfs/Resetter.h
+++ b/src/tools/cephfs/Resetter.h
@@ -36,8 +36,8 @@ public:
* For use when no journal header/pointer was present: write one
* out from scratch.
*/
- int reset_hard(int rank);
- int reset(int rank);
+ int reset_hard(mds_role_t role);
+ int reset(mds_role_t role);
};
#endif /* JOURNAL_RESETTER_H_ */
diff --git a/src/tools/cephfs/RoleSelector.cc b/src/tools/cephfs/RoleSelector.cc
new file mode 100644
index 00000000000..b352c4cad9c
--- /dev/null
+++ b/src/tools/cephfs/RoleSelector.cc
@@ -0,0 +1,58 @@
+
+#include "RoleSelector.h"
+
+int MDSRoleSelector::parse_rank(
+ const FSMap &fsmap,
+ std::string const &str)
+{
+ if (str == "all" || str == "*") {
+ std::set<mds_rank_t> in;
+ const MDSMap &mds_map = fsmap.get_filesystem(fscid)->mds_map;
+ mds_map.get_mds_set(in);
+
+ for (auto rank : in) {
+ roles.push_back(mds_role_t(fscid, rank));
+ }
+
+ return 0;
+ } else {
+ std::string rank_err;
+ mds_rank_t rank = strict_strtol(str.c_str(), 10, &rank_err);
+ if (!rank_err.empty()) {
+ return -EINVAL;
+ }
+ if (fsmap.get_filesystem(fscid)->mds_map.is_dne(rank)) {
+ return -ENOENT;
+ }
+ roles.push_back(mds_role_t(fscid, rank));
+ return 0;
+ }
+}
+
+int MDSRoleSelector::parse(const FSMap &fsmap, std::string const &str)
+{
+ auto colon_pos = str.find(":");
+ if (colon_pos == std::string::npos) {
+ // An unqualified rank. Only valid if there is only one
+ // namespace.
+ if (fsmap.get_filesystems().size() == 1) {
+ fscid = fsmap.get_filesystems().begin()->first;
+ return parse_rank(fsmap, str);
+ } else {
+ return -EINVAL;
+ }
+ } else if (colon_pos == 0 || colon_pos == str.size() - 1) {
+ return -EINVAL;
+ } else {
+ const std::string ns_str = str.substr(0, colon_pos);
+ const std::string rank_str = str.substr(colon_pos + 1);
+ std::shared_ptr<Filesystem> fs_ptr;
+ int r = fsmap.parse_filesystem(ns_str, &fs_ptr);
+ if (r != 0) {
+ return r;
+ }
+ fscid = fs_ptr->fscid;
+ return parse_rank(fsmap, rank_str);
+ }
+}
+
diff --git a/src/tools/cephfs/RoleSelector.h b/src/tools/cephfs/RoleSelector.h
new file mode 100644
index 00000000000..933c51d0f78
--- /dev/null
+++ b/src/tools/cephfs/RoleSelector.h
@@ -0,0 +1,35 @@
+
+#ifndef ROLE_SELECTOR_H_
+#define ROLE_SELECTOR_H_
+
+#include <string>
+#include <vector>
+#include "mds/mdstypes.h"
+#include "mds/FSMap.h"
+
+/**
+ * When you want to let the user act on a single rank in a namespace,
+ * or all of them.
+ */
+class MDSRoleSelector
+{
+ public:
+ const std::vector<mds_role_t> &get_roles() const {return roles;}
+ int parse(const FSMap &fsmap, std::string const &str);
+ MDSRoleSelector()
+ : fscid(FS_CLUSTER_ID_NONE)
+ {}
+ fs_cluster_id_t get_ns() const
+ {
+ return fscid;
+ }
+ protected:
+ int parse_rank(
+ const FSMap &fsmap,
+ std::string const &str);
+ std::vector<mds_role_t> roles;
+ fs_cluster_id_t fscid;
+};
+
+#endif // ROLE_SELECTOR_H_
+
diff --git a/src/tools/cephfs/TableTool.cc b/src/tools/cephfs/TableTool.cc
index 2d14a4f9286..2ff020a6de6 100644
--- a/src/tools/cephfs/TableTool.cc
+++ b/src/tools/cephfs/TableTool.cc
@@ -38,38 +38,32 @@ void TableTool::usage()
/**
- * For a function that takes an MDS rank as an argument and
- * returns an error code, execute it either on all ranks (if
- * this->rank is MDS_RANK_NONE), or on the rank specified
- * by this->rank.
+ * For a function that takes an MDS role as an argument and
+ * returns an error code, execute it on the roles specified
+ * by `role_selector`.
*/
-int TableTool::apply_rank_fn(std::function<int(mds_rank_t, Formatter *)> fptr, Formatter *f)
+int TableTool::apply_role_fn(std::function<int(mds_role_t, Formatter *)> fptr, Formatter *f)
{
assert(f != NULL);
int r = 0;
- std::set<mds_rank_t> apply_to_ranks;
- if (rank == MDS_RANK_NONE) {
- mdsmap->get_mds_set(apply_to_ranks);
- } else {
- apply_to_ranks.insert(rank);
- }
f->open_object_section("ranks");
- for (std::set<mds_rank_t>::iterator rank_i = apply_to_ranks.begin();
- rank_i != apply_to_ranks.end(); ++rank_i) {
+ for (auto role : role_selector.get_roles()) {
std::ostringstream rank_str;
- rank_str << *rank_i;
+ rank_str << role.rank;
f->open_object_section(rank_str.str().c_str());
f->open_object_section("data");
- int rank_r = fptr(*rank_i, f);
+ int rank_r = fptr(role, f);
f->close_section();
r = r ? r : rank_r;
f->dump_int("result", rank_r);
f->close_section();
+
+
}
f->close_section();
@@ -90,21 +84,21 @@ protected:
// The RADOS object ID for the table
std::string object_name;
- // The rank in question (may be NONE)
- mds_rank_t rank;
+ // The role in question (may be NONE)
+ mds_role_t role;
// Whether this is an MDSTable subclass (i.e. has leading version field to decode)
bool mds_table;
public:
- TableHandler(mds_rank_t r, std::string const &name, bool mds_table_)
- : rank(r), mds_table(mds_table_)
+ TableHandler(mds_role_t r, std::string const &name, bool mds_table_)
+ : role(r), mds_table(mds_table_)
{
// Compose object name of the table we will dump
std::ostringstream oss;
oss << "mds";
- if (rank != MDS_RANK_NONE) {
- oss << rank;
+ if (!role.is_none()) {
+ oss << role.rank;
}
oss << "_" << name;
object_name = oss.str();
@@ -127,7 +121,7 @@ public:
f->dump_int("version", version);
}
A table_inst;
- table_inst.set_rank(rank);
+ table_inst.set_rank(role.rank);
table_inst.decode(q);
table_inst.dump(f);
@@ -147,7 +141,7 @@ public:
{
A table_inst;
// Compose new (blank) table
- table_inst.set_rank(rank);
+ table_inst.set_rank(role.rank);
table_inst.reset_state();
// Write the table out
return write(table_inst, io);
@@ -183,21 +177,21 @@ private:
// The RADOS object ID for the table
std::string object_name;
- // The rank in question (may be NONE)
- mds_rank_t rank;
+ // The role (rank may be NONE)
+ mds_role_t role;
// Whether this is an MDSTable subclass (i.e. has leading version field to decode)
bool mds_table;
public:
- TableHandlerOmap(mds_rank_t r, std::string const &name, bool mds_table_)
- : rank(r), mds_table(mds_table_)
+ TableHandlerOmap(mds_role_t r, std::string const &name, bool mds_table_)
+ : role(r), mds_table(mds_table_)
{
// Compose object name of the table we will dump
std::ostringstream oss;
oss << "mds";
- if (rank != MDS_RANK_NONE) {
- oss << rank;
+ if (!role.is_none()) {
+ oss << role.rank;
}
oss << "_" << name;
object_name = oss.str();
@@ -212,13 +206,14 @@ public:
bufferlist header_bl;
int r = io->omap_get_header(object_name, &header_bl);
if (r != 0) {
- derr << "error reading header: " << cpp_strerror(r) << dendl;
+ derr << "error reading header on '" << object_name << "': "
+ << cpp_strerror(r) << dendl;
return r;
}
// Decode the header
A table_inst;
- table_inst.set_rank(rank);
+ table_inst.set_rank(role.rank);
try {
table_inst.decode_header(header_bl);
} catch (buffer::error &e) {
@@ -259,7 +254,7 @@ public:
int reset(librados::IoCtx *io)
{
A table_inst;
- table_inst.set_rank(rank);
+ table_inst.set_rank(role.rank);
table_inst.reset_state();
bufferlist header_bl;
table_inst.encode_header(&header_bl);
@@ -277,14 +272,14 @@ public:
class InoTableHandler : public TableHandler<InoTable>
{
public:
- explicit InoTableHandler(mds_rank_t r)
+ explicit InoTableHandler(mds_role_t r)
: TableHandler(r, "inotable", true)
{}
int take_inos(librados::IoCtx *io, inodeno_t max, Formatter *f)
{
InoTable inst;
- inst.set_rank(rank);
+ inst.set_rank(role.rank);
inst.reset_state();
int r = 0;
@@ -317,18 +312,7 @@ int TableTool::main(std::vector<const char*> &argv)
dout(4) << "connecting to RADOS..." << dendl;
rados.connect();
- int const pool_id = mdsmap->get_metadata_pool();
- dout(4) << "resolving pool " << pool_id << dendl;
- std::string pool_name;
- r = rados.pool_reverse_lookup(pool_id, &pool_name);
- if (r < 0) {
- derr << "Pool " << pool_id << " identified in MDS map not found in RADOS!" << dendl;
- return r;
- }
- dout(4) << "creating IoCtx.." << dendl;
- r = rados.ioctx_create(pool_name.c_str(), io);
- assert(r == 0);
// Require at least 3 args <rank> <mode> <arg> [args...]
if (argv.size() < 3) {
@@ -336,33 +320,47 @@ int TableTool::main(std::vector<const char*> &argv)
return -EINVAL;
}
- const std::string rank_str = std::string(argv[0]);
+ const std::string role_str = std::string(argv[0]);
const std::string mode = std::string(argv[1]);
+ const std::string table = std::string(argv[2]);
- if (rank_str == "all") {
- rank = MDS_RANK_NONE;
- } else {
- std::string rank_err;
- rank = strict_strtol(rank_str.c_str(), 10, &rank_err);
- if (!rank_err.empty()) {
- derr << "Bad rank '" << rank_str << "'" << dendl;
- usage();
- }
+ r = role_selector.parse(*fsmap, role_str);
+ if (r < 0) {
+ derr << "Bad rank selection: " << role_str << "'" << dendl;
+ return r;
+ }
+
+ auto fs = fsmap->get_filesystem(role_selector.get_ns());
+ assert(fs != nullptr);
+ int const pool_id = fs->mds_map.get_metadata_pool();
+ dout(4) << "resolving pool " << pool_id << dendl;
+ std::string pool_name;
+ r = rados.pool_reverse_lookup(pool_id, &pool_name);
+ if (r < 0) {
+ derr << "Pool " << pool_id << " identified in MDS map not found in RADOS!"
+ << dendl;
+ return r;
+ }
+
+ dout(4) << "creating IoCtx.." << dendl;
+ r = rados.ioctx_create(pool_name.c_str(), io);
+ if (r != 0) {
+ return r;
}
JSONFormatter jf(true);
if (mode == "reset") {
const std::string table = std::string(argv[2]);
if (table == "session") {
- r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
+ r = apply_role_fn([this](mds_role_t rank, Formatter *f) -> int {
return TableHandlerOmap<SessionMapStore>(rank, "sessionmap", false).reset(&io);
}, &jf);
} else if (table == "inode") {
- r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
+ r = apply_role_fn([this](mds_role_t rank, Formatter *f) -> int {
return TableHandler<InoTable>(rank, "inotable", true).reset(&io);
}, &jf);
} else if (table == "snap") {
- r = TableHandler<SnapServer>(MDS_RANK_NONE, "snaptable", true).reset(&io);
+ r = TableHandler<SnapServer>(mds_role_t(), "snaptable", true).reset(&io);
jf.open_object_section("reset_snap_status");
jf.dump_int("result", r);
jf.close_section();
@@ -375,18 +373,18 @@ int TableTool::main(std::vector<const char*> &argv)
} else if (mode == "show") {
const std::string table = std::string(argv[2]);
if (table == "session") {
- r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
+ r = apply_role_fn([this](mds_role_t rank, Formatter *f) -> int {
return TableHandlerOmap<SessionMapStore>(rank, "sessionmap", false).load_and_dump(&io, f);
}, &jf);
} else if (table == "inode") {
- r = apply_rank_fn([this](mds_rank_t rank, Formatter *f) -> int {
+ r = apply_role_fn([this](mds_role_t rank, Formatter *f) -> int {
return TableHandler<InoTable>(rank, "inotable", true).load_and_dump(&io, f);;
}, &jf);
} else if (table == "snap") {
jf.open_object_section("show_snap_table");
{
r = TableHandler<SnapServer>(
- MDS_RANK_NONE, "snaptable", true).load_and_dump(&io, &jf);
+ mds_role_t(), "snaptable", true).load_and_dump(&io, &jf);
jf.dump_int("result", r);
}
jf.close_section();
@@ -403,7 +401,7 @@ int TableTool::main(std::vector<const char*> &argv)
derr << "Bad ino '" << ino_str << "'" << dendl;
return -EINVAL;
}
- r = apply_rank_fn([this, ino](mds_rank_t rank, Formatter *f) -> int {
+ r = apply_role_fn([this, ino](mds_role_t rank, Formatter *f) -> int {
return InoTableHandler(rank).take_inos(&io, ino, f);
}, &jf);
} else {
diff --git a/src/tools/cephfs/TableTool.h b/src/tools/cephfs/TableTool.h
index 57705ef1711..bcd3167b29e 100644
--- a/src/tools/cephfs/TableTool.h
+++ b/src/tools/cephfs/TableTool.h
@@ -13,10 +13,10 @@
#include "MDSUtility.h"
+#include "RoleSelector.h"
#include "include/rados/librados.hpp"
-
/**
* Command line tool for debugging the backing store of
* MDSTable instances.
@@ -24,18 +24,17 @@
class TableTool : public MDSUtility
{
private:
- mds_rank_t rank;
+ MDSRoleSelector role_selector;
// I/O handles
librados::Rados rados;
librados::IoCtx io;
- int apply_rank_fn(std::function<int(mds_rank_t, Formatter *)> fptr, Formatter *f);
+ int apply_role_fn(std::function<int(mds_role_t, Formatter *)> fptr, Formatter *f);
public:
void usage();
- TableTool() :
- rank(MDS_RANK_NONE) {}
int main(std::vector<const char*> &argv);
};
+