From: John Spray Date: Thu, 30 Apr 2015 10:44:04 +0000 (+0100) Subject: tools: improve journaltool reset X-Git-Tag: v9.0.2~184^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a4925933d37a720ae81f98392982b32d1b4a20ca;p=ceph.git tools: improve journaltool reset Handle the case where no journal objects exist at all, rather than just resetting a journal that already exists. Signed-off-by: John Spray --- diff --git a/src/tools/cephfs/JournalTool.cc b/src/tools/cephfs/JournalTool.cc index 611832043594..1bc7b79afc4f 100644 --- a/src/tools/cephfs/JournalTool.cc +++ b/src/tools/cephfs/JournalTool.cc @@ -41,7 +41,12 @@ void JournalTool::usage() { std::cout << "Usage: \n" - << " cephfs-journal-tool [options] journal [inspect|import|export|reset]\n" + << " cephfs-journal-tool [options] journal \n" + << " :\n" + << " inspect\n" + << " import \n" + << " export \n" + << " reset [--force]\n" << " cephfs-journal-tool [options] header \n" << " cephfs-journal-tool [options] event \n" << " :\n" @@ -155,7 +160,21 @@ int JournalTool::main_journal(std::vector &argv) return -EINVAL; } } else if (command == "reset") { - return journal_reset(); + bool force = false; + if (argv.size() == 2) { + if (std::string(argv[1]) == "--force") { + force = true; + } else { + std::cerr << "Unknown argument " << argv[1] << std::endl; + usage(); + return -EINVAL; + } + } else if (argv.size() > 2) { + std::cerr << "Too many arguments!" << std::endl; + usage(); + return -EINVAL; + } + return journal_reset(force); } else { derr << "Bad journal command '" << command << "'" << dendl; return -EINVAL; @@ -529,7 +548,7 @@ int JournalTool::journal_export(std::string const &path, bool import) /** * Truncate journal and insert EResetJournal */ -int JournalTool::journal_reset() +int JournalTool::journal_reset(bool hard) { int r = 0; Resetter resetter; @@ -538,7 +557,17 @@ int JournalTool::journal_reset() derr << "resetter::init failed: " << cpp_strerror(r) << dendl; return r; } - resetter.reset(rank); + + if (mdsmap->is_dne(mds_rank_t(rank))) { + std::cerr << "MDS rank " << rank << " does not exist" << std::endl; + return -ENOENT; + } + + if (hard) { + resetter.reset_hard(rank); + } else { + resetter.reset(rank); + } resetter.shutdown(); return r; diff --git a/src/tools/cephfs/JournalTool.h b/src/tools/cephfs/JournalTool.h index 24722c23162b..f717859a6f14 100644 --- a/src/tools/cephfs/JournalTool.h +++ b/src/tools/cephfs/JournalTool.h @@ -45,7 +45,7 @@ class JournalTool : public MDSUtility // Journal operations int journal_inspect(); int journal_export(std::string const &path, bool import); - int journal_reset(); + int journal_reset(bool hard); // Header operations int header_set(); diff --git a/src/tools/cephfs/Resetter.cc b/src/tools/cephfs/Resetter.cc index 5fb8997f1be5..b96ea028fd18 100644 --- a/src/tools/cephfs/Resetter.cc +++ b/src/tools/cephfs/Resetter.cc @@ -17,11 +17,13 @@ #include "mds/JournalPointer.h" #include "mds/mdstypes.h" +#include "mds/MDCache.h" #include "mon/MonClient.h" #include "mds/events/EResetJournal.h" #include "Resetter.h" +#define dout_subsys ceph_subsys_mds void Resetter::reset(int rank) { @@ -33,7 +35,8 @@ void Resetter::reset(int rank) JournalPointer jp(rank, mdsmap->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; + std::cerr << "Error loading journal: " << cpp_strerror(jp_load_result) << + ", pass --force to forcibly reset this journal" << std::endl; return; } @@ -55,6 +58,15 @@ void Resetter::reset(int rank) if (r == -ENOENT) { cerr << "journal does not exist on-disk. Did you set a bad rank?" << std::endl; + std::cerr << "Error loading journal: " << cpp_strerror(jp_load_result) << + ", pass --force to forcibly reset this journal" << std::endl; + std::cerr << "Falling back to hard reset..." << std::endl; + r = reset_hard(rank); + if (r != 0) { + std::cerr << "Hard reset failed: " << cpp_strerror(r) << std::endl; + } else { + std::cerr << "Hard reset successful." << std::endl; + } return; } else { cerr << "got error " << r << "from Journaler, failling" << std::endl; @@ -90,23 +102,73 @@ void Resetter::reset(int rank) lock.Lock(); assert(r == 0); + r = _write_reset_event(&journaler); + assert(r == 0); + + lock.Unlock(); + + cout << "done" << std::endl; +} + +int Resetter::reset_hard(int rank) +{ + JournalPointer jp(rank, mdsmap->get_metadata_pool()); + jp.front = rank + MDS_INO_LOG_OFFSET; + jp.back = 0; + int r = jp.save(objecter); + if (r != 0) { + derr << "Error writing journal pointer: " << cpp_strerror(r) << dendl; + return r; + } + + Journaler journaler(jp.front, + mdsmap->get_metadata_pool(), + CEPH_FS_ONDISK_MAGIC, + objecter, 0, 0, &timer, &finisher); + journaler.set_writeable(); + + ceph_file_layout default_log_layout = MDCache::gen_default_log_layout(*mdsmap); + journaler.create(&default_log_layout, g_conf->mds_journal_format); + + C_SaferCond cond; + { + Mutex::Locker l(lock); + journaler.write_head(&cond); + } + r = cond.wait(); + if (r != 0) { + derr << "Error writing journal header: " << cpp_strerror(r) << dendl; + return r; + } + + { + Mutex::Locker l(lock); + r = _write_reset_event(&journaler); + } + if (r != 0) { + derr << "Error writing EResetJournal: " << cpp_strerror(r) << dendl; + return r; + } + + dout(4) << "Successfully wrote new journal pointer and header for rank " + << rank << dendl; + return 0; +} + +int Resetter::_write_reset_event(Journaler *journaler) +{ + assert(journaler != NULL); + LogEvent *le = new EResetJournal; bufferlist bl; le->encode_with_header(bl); cout << "writing EResetJournal entry" << std::endl; - journaler.append_entry(bl); - journaler.flush(new C_SafeCond(&mylock, &cond, &done,&r)); - - lock.Unlock(); + C_SaferCond cond; + journaler->append_entry(bl); + journaler->flush(&cond); - mylock.Lock(); - while (!done) - cond.Wait(mylock); - mylock.Unlock(); - - assert(r == 0); - - cout << "done" << std::endl; + return cond.wait(); } + diff --git a/src/tools/cephfs/Resetter.h b/src/tools/cephfs/Resetter.h index be1053801db1..6f29d67c48fd 100644 --- a/src/tools/cephfs/Resetter.h +++ b/src/tools/cephfs/Resetter.h @@ -17,6 +17,8 @@ #include "MDSUtility.h" +class Journaler; + /** * This class lets you reset an mds journal for troubleshooting or whatever. * @@ -24,10 +26,17 @@ * of the file to dump to. */ class Resetter : public MDSUtility { - int rank; +protected: + int _write_reset_event(Journaler *journaler); + public: Resetter() {} + /** + * For use when no journal header/pointer was present: write one + * out from scratch. + */ + int reset_hard(int rank); void reset(int rank); };