diff options
author | John Spray <john.spray@redhat.com> | 2016-02-17 15:57:17 +0100 |
---|---|---|
committer | John Spray <john.spray@redhat.com> | 2016-03-10 13:11:23 +0100 |
commit | 0ed5eb7a8e31448979c0725aa49fe35ca38a5f29 (patch) | |
tree | 867c1094792ec360a5170864a00532c540ab853d /src/tools/cephfs | |
parent | mon: update for multiple filesystems (diff) | |
download | ceph-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.cc | 48 | ||||
-rw-r--r-- | src/tools/cephfs/DataScan.h | 20 | ||||
-rw-r--r-- | src/tools/cephfs/Dumper.cc | 26 | ||||
-rw-r--r-- | src/tools/cephfs/Dumper.h | 8 | ||||
-rw-r--r-- | src/tools/cephfs/JournalTool.cc | 68 | ||||
-rw-r--r-- | src/tools/cephfs/JournalTool.h | 6 | ||||
-rw-r--r-- | src/tools/cephfs/MDSUtility.cc | 18 | ||||
-rw-r--r-- | src/tools/cephfs/MDSUtility.h | 8 | ||||
-rw-r--r-- | src/tools/cephfs/Resetter.cc | 27 | ||||
-rw-r--r-- | src/tools/cephfs/Resetter.h | 4 | ||||
-rw-r--r-- | src/tools/cephfs/RoleSelector.cc | 58 | ||||
-rw-r--r-- | src/tools/cephfs/RoleSelector.h | 35 | ||||
-rw-r--r-- | src/tools/cephfs/TableTool.cc | 122 | ||||
-rw-r--r-- | src/tools/cephfs/TableTool.h | 9 |
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); }; + |