void JournalTool::usage()
{
std::cout << "Usage: \n"
- << " cephfs-journal-tool [options] journal [inspect|import|export|reset]\n"
+ << " cephfs-journal-tool [options] journal <command>\n"
+ << " <command>:\n"
+ << " inspect\n"
+ << " import <path>\n"
+ << " export <path>\n"
+ << " reset [--force]\n"
<< " cephfs-journal-tool [options] header <get|set <field> <value>\n"
<< " cephfs-journal-tool [options] event <effect> <selector> <output>\n"
<< " <selector>:\n"
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;
/**
* Truncate journal and insert EResetJournal
*/
-int JournalTool::journal_reset()
+int JournalTool::journal_reset(bool hard)
{
int r = 0;
Resetter resetter;
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;
#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)
{
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;
}
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;
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();
}
+