]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tools: improve journaltool reset
authorJohn Spray <john.spray@redhat.com>
Thu, 30 Apr 2015 10:44:04 +0000 (11:44 +0100)
committerJohn Spray <john.spray@redhat.com>
Tue, 12 May 2015 09:23:27 +0000 (10:23 +0100)
Handle the case where no journal objects exist at all,
rather than just resetting a journal that already exists.

Signed-off-by: John Spray <john.spray@redhat.com>
src/tools/cephfs/JournalTool.cc
src/tools/cephfs/JournalTool.h
src/tools/cephfs/Resetter.cc
src/tools/cephfs/Resetter.h

index 6118320435948c83652b001a47b3e55212ca0490..1bc7b79afc4f5b624d0842f3c170365bef20b014 100644 (file)
 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"
@@ -155,7 +160,21 @@ int JournalTool::main_journal(std::vector<const char*> &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;
index 24722c23162bfe7bba61727925a1977da841ed29..f717859a6f14d3929305b444bf02d1fd7c90eb42 100644 (file)
@@ -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();
index 5fb8997f1be56fa108166e676d64864cefbc9fcc..b96ea028fd18acb48a2c08de5c131087d3d89902 100644 (file)
 #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();
 }
+
index be1053801db1b42143b1de8ac8f0e958051a2c0a..6f29d67c48fd0bd3c55011f8143ef6361122d6ce 100644 (file)
@@ -17,6 +17,8 @@
 
 #include "MDSUtility.h"
 
+class Journaler;
+
 /**
  * This class lets you reset an mds journal for troubleshooting or whatever.
  *
  * 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);
 };