]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cephfs-journal-tool: support purge queue 19471/head
authordongdong tao <tdd21151186@gmail.com>
Sun, 10 Dec 2017 07:21:28 +0000 (15:21 +0800)
committerdongdong tao <tdd21151186@gmail.com>
Sat, 17 Feb 2018 07:00:57 +0000 (15:00 +0800)
Add option "--journal" to identify the journal type.
this patch can fully support mode "journal" and "header" for purge queue.
As mode "event" is only specific for "mdlog", "journal" and "header" mode only contain
pure "Journaler" operation.

Signed-off-by: dongdong tao <tdd21151186@gmail.com>
src/tools/cephfs/Dumper.cc
src/tools/cephfs/Dumper.h
src/tools/cephfs/JournalScanner.cc
src/tools/cephfs/JournalScanner.h
src/tools/cephfs/JournalTool.cc
src/tools/cephfs/JournalTool.h
src/tools/cephfs/Resetter.cc
src/tools/cephfs/Resetter.h

index 22ef544a8f364cdc78b30ba8fcd6ec429214b46d..67252eaa326fbee75a9d1273a9e6ff3c8b9fd2fc 100644 (file)
@@ -33,7 +33,7 @@
 
 #define HEADER_LEN 4096
 
-int Dumper::init(mds_role_t role_)
+int Dumper::init(mds_role_t role_, const std::string &type)
 {
   role = role_;
 
@@ -45,15 +45,21 @@ int Dumper::init(mds_role_t role_)
   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;
-    return jp_load_result;
+  if (type == "mdlog") {
+    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;
+      return jp_load_result;
+    } else {
+      ino = jp.front;
+    }
+  } else if (type == "purge_queue") {
+    ino = MDS_INO_PURGE_QUEUE + role.rank;
   } else {
-    ino = jp.front;
-    return 0;
+    ceph_abort(); // should not get here 
   }
+  return 0;
 }
 
 
index f95a06290dbe8284ff05dc312e53b74faaa29318..aad7b3e10a59f1081e79c334bb4b15d5edbea799 100644 (file)
@@ -36,7 +36,7 @@ public:
   Dumper() : ino(-1)
   {}
 
-  int init(mds_role_t role_);
+  int init(mds_role_t role_, const std::string &type);
   int recover_journal(Journaler *journaler);
   int dump(const char *dumpfile);
   int undump(const char *dumpfile);
index 7c359a9c4355a36cb10a10324608ed0f631e6785..cb2ea244a09da323d98623a228456a68fc778473 100644 (file)
@@ -16,6 +16,7 @@
 #include "mds/JournalPointer.h"
 
 #include "mds/events/ESubtreeMap.h"
+#include "mds/PurgeQueue.h"
 
 #include "JournalScanner.h"
 
@@ -33,12 +34,12 @@ int JournalScanner::scan(bool const full)
 {
   int r = 0;
 
-  r = scan_pointer();
+  r = set_journal_ino();
   if (r < 0) {
     return r;
   }
 
-  if (pointer_present) {
+  if (!is_mdlog || pointer_present) {
     r = scan_header();
     if (r < 0) {
       return r;
@@ -56,6 +57,22 @@ int JournalScanner::scan(bool const full)
 }
 
 
+int JournalScanner::set_journal_ino()
+{
+  int r = 0;
+  if (type == "purge_queue") {
+    ino = MDS_INO_PURGE_QUEUE + rank;
+  }
+  else if (type == "mdlog"){
+    r = scan_pointer();
+    is_mdlog = true;
+  }
+  else {
+    ceph_abort(); // should not get here
+  }
+  return r;
+}
+
 int JournalScanner::scan_pointer()
 {
   // Issue read
@@ -257,36 +274,52 @@ int JournalScanner::scan_events()
           read_offset += consumed;
           break;
         }
-
-        LogEvent *le = LogEvent::decode(le_bl);
-
-        if (le) {
-          dout(10) << "Valid entry at 0x" << std::hex << read_offset << std::dec << dendl;
-
-          if (le->get_type() == EVENT_SUBTREEMAP
-              || le->get_type() == EVENT_SUBTREEMAP_TEST) {
-            ESubtreeMap *sle = dynamic_cast<ESubtreeMap*>(le);
-            if (sle->expire_pos > read_offset) {
-              errors.insert(std::make_pair(
-                    read_offset, EventError(
-                      -ERANGE,
-                      "ESubtreeMap has expire_pos ahead of its own position")));
+        bool valid_entry = true;
+        if (is_mdlog) {
+          LogEvent *le = LogEvent::decode(le_bl);
+
+          if (le) {
+            dout(10) << "Valid entry at 0x" << std::hex << read_offset << std::dec << dendl;
+
+            if (le->get_type() == EVENT_SUBTREEMAP
+                || le->get_type() == EVENT_SUBTREEMAP_TEST) {
+              ESubtreeMap *sle = dynamic_cast<ESubtreeMap*>(le);
+              if (sle->expire_pos > read_offset) {
+                errors.insert(std::make_pair(
+                      read_offset, EventError(
+                        -ERANGE,
+                        "ESubtreeMap has expire_pos ahead of its own position")));
+              }
             }
-          }
 
-          if (filter.apply(read_offset, *le)) {
-            events[read_offset] = EventRecord(le, consumed);
+            if (filter.apply(read_offset, *le)) {
+              events[read_offset] = EventRecord(le, consumed);
+            } else {
+              delete le;
+            }
           } else {
-            delete le;
+            valid_entry = false;
           }
-          events_valid.push_back(read_offset);
-          read_offset += consumed;
+        } else if (type == "purge_queue"){
+           PurgeItem pi;
+           try {
+             bufferlist::iterator q = le_bl.begin();
+             ::decode(pi, q);
+           } catch (const buffer::error &err) {
+             valid_entry = false;
+           }
         } else {
+          ceph_abort(); // should not get here
+        }
+        if (!valid_entry) {
           dout(10) << "Invalid entry at 0x" << std::hex << read_offset << std::dec << dendl;
           gap = true;
           gap_start = read_offset;
           read_offset += consumed;
           break;
+        } else {
+          events_valid.push_back(read_offset);
+          read_offset += consumed;
         }
       }
     }
@@ -325,7 +358,7 @@ JournalScanner::~JournalScanner()
  */
 bool JournalScanner::is_healthy() const
 {
-  return (pointer_present && pointer_valid
+  return ((!is_mdlog || (pointer_present && pointer_valid))
       && header_present && header_valid
       && ranges_invalid.empty()
       && objects_missing.empty());
@@ -367,12 +400,13 @@ void JournalScanner::report(std::ostream &out) const
 {
   out << "Overall journal integrity: " << (is_healthy() ? "OK" : "DAMAGED") << std::endl;
 
-  if (!pointer_present) {
-    out << "Pointer not found" << std::endl;
-  } else if (!pointer_valid) {
-    out << "Pointer could not be decoded" << std::endl;
+  if (is_mdlog) {
+    if (!pointer_present) {
+      out << "Pointer not found" << std::endl;
+    } else if (!pointer_valid) {
+      out << "Pointer could not be decoded" << std::endl;
+    }
   }
-
   if (!header_present) {
     out << "Header not found" << std::endl;
   } else if (!header_valid) {
index e6aaa05e11e24349b981f077e28084dddbcce5ec..dad7dc5ac65c57a11af76969483763d913970e25 100644 (file)
@@ -36,6 +36,7 @@ class JournalScanner
 
   // Input constraints
   const int rank;
+  std::string type;
   JournalFilter const filter;
 
   void gap_advance();
@@ -44,10 +45,13 @@ class JournalScanner
   JournalScanner(
       librados::IoCtx &io_,
       int rank_,
+      const std::string &type_,
       JournalFilter const &filter_) :
     io(io_),
     rank(rank_),
+    type(type_),
     filter(filter_),
+    is_mdlog(false),
     pointer_present(false),
     pointer_valid(false),
     header_present(false),
@@ -56,9 +60,12 @@ class JournalScanner
 
   JournalScanner(
       librados::IoCtx &io_,
-      int rank_) :
+      int rank_,
+      const std::string &type_) :
     io(io_),
     rank(rank_),
+    type(type_),
+    is_mdlog(false),
     pointer_present(false),
     pointer_valid(false),
     header_present(false),
@@ -67,6 +74,7 @@ class JournalScanner
 
   ~JournalScanner();
 
+  int set_journal_ino();
   int scan(bool const full=true);
   int scan_pointer();
   int scan_header();
@@ -77,7 +85,7 @@ class JournalScanner
   std::string obj_name(inodeno_t ino, uint64_t offset) const;
 
   // The results of the scan
-  inodeno_t ino;  // Corresponds to JournalPointer.front
+  inodeno_t ino;  // Corresponds to journal ino according their type
   class EventRecord {
     public:
     EventRecord() : log_event(NULL), raw_size(0) {}
@@ -97,8 +105,9 @@ class JournalScanner
   typedef std::map<uint64_t, EventRecord> EventMap;
   typedef std::map<uint64_t, EventError> ErrorMap;
   typedef std::pair<uint64_t, uint64_t> Range;
-  bool pointer_present;
-  bool pointer_valid;
+  bool is_mdlog;
+  bool pointer_present; //mdlog specific
+  bool pointer_valid;   //mdlog specific
   bool header_present;
   bool header_valid;
   Journaler::Header *header;
index 4a30634f40a0e0de61babed5413a6a3fcada9723..2af6a918c3fad4de4592329454e27c82f7c93a2b 100644 (file)
@@ -64,7 +64,10 @@ void JournalTool::usage()
     << "General options:\n"
     << "  --rank=filesystem:mds-rank  Journal rank (required if multiple\n"
     << "                              file systems, default is rank 0 on\n"
-    << "                              the only filesystem otherwise.\n"
+    << "                              the only filesystem otherwise.)\n"
+    << "  --journal=<mdlog|purge_queue>  Journal type (purge_queue means\n"
+    << "                                 this journal is used to queue for purge operation,\n"
+    << "                                 default is mdlog, and only mdlog support event mode)\n" 
     << "\n"
     << "Special options\n"
     << "  --alternate-pool <name>     Alternative metadata pool to target\n"
@@ -92,12 +95,23 @@ 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)) {
+  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";
   }
 
+  if (!ceph_argparse_witharg(argv, arg, &type, "--journal", (char*)NULL)) {
+    // Default is mdlog
+    type = "mdlog";
+  }
+  
+  r = validate_type(type);
+  if (r != 0) {
+    derr << "journal type is not correct." << dendl;
+    return r;
+  }
+
   r = role_selector.parse(*fsmap, rank_str);
   if (r != 0) {
     derr << "Couldn't determine MDS rank." << dendl;
@@ -145,6 +159,8 @@ int JournalTool::main(std::vector<const char*> &argv)
 
   // Execution
   // =========
+  // journal and header are general journal mode
+  // event mode is only specific for mdlog
   for (auto role : role_selector.get_roles()) {
     rank = role.rank;
     dout(4) << "Executing for rank " << rank << dendl;
@@ -152,7 +168,7 @@ int JournalTool::main(std::vector<const char*> &argv)
       r = main_journal(argv);
     } else if (mode == std::string("header")) {
       r = main_header(argv);
-    } else if (mode == std::string("event")) {
+    } else if (type == std::string("mdlog") && mode == std::string("event")) {
       r = main_event(argv);
     } else {
       derr << "Bad command '" << mode << "'" << dendl;
@@ -168,6 +184,13 @@ int JournalTool::main(std::vector<const char*> &argv)
   return r;
 }
 
+int JournalTool::validate_type(const std::string &type)
+{
+  if (type == "mdlog" || type == "purge_queue") {
+    return 0;
+  }
+  return -1;
+}
 
 /**
  * Handle arguments for 'journal' mode
@@ -218,7 +241,7 @@ int JournalTool::main_journal(std::vector<const char*> &argv)
 int JournalTool::main_header(std::vector<const char*> &argv)
 {
   JournalFilter filter;
-  JournalScanner js(input, rank, filter);
+  JournalScanner js(input, rank, type, filter);
   int r = js.scan(false);
   if (r < 0) {
     std::cerr << "Unable to scan journal" << std::endl;
@@ -369,7 +392,7 @@ int JournalTool::main_event(std::vector<const char*> &argv)
 
   // Execute command
   // ===============
-  JournalScanner js(input, rank, filter);
+  JournalScanner js(input, rank, type, filter);
   if (command == "get") {
     r = js.scan();
     if (r) {
@@ -516,7 +539,7 @@ int JournalTool::journal_inspect()
   int r;
 
   JournalFilter filter;
-  JournalScanner js(input, rank, filter);
+  JournalScanner js(input, rank, type, filter);
   r = js.scan();
   if (r) {
     std::cerr << "Failed to scan journal (" << cpp_strerror(r) << ")" << std::endl;
@@ -540,7 +563,7 @@ int JournalTool::journal_inspect()
 int JournalTool::journal_export(std::string const &path, bool import)
 {
   int r = 0;
-  JournalScanner js(input, rank);
+  JournalScanner js(input, rank, type);
 
   if (!import) {
     /*
@@ -563,7 +586,7 @@ int JournalTool::journal_export(std::string const &path, bool import)
    */
   {
     Dumper dumper;
-    r = dumper.init(mds_role_t(role_selector.get_ns(), rank));
+    r = dumper.init(mds_role_t(role_selector.get_ns(), rank), type);
     if (r < 0) {
       derr << "dumper::init failed: " << cpp_strerror(r) << dendl;
       return r;
@@ -586,16 +609,16 @@ int JournalTool::journal_reset(bool hard)
 {
   int r = 0;
   Resetter resetter;
-  r = resetter.init();
+  r = resetter.init(mds_role_t(role_selector.get_ns(), rank), type, hard);
   if (r < 0) {
     derr << "resetter::init failed: " << cpp_strerror(r) << dendl;
     return r;
   }
 
   if (hard) {
-    r = resetter.reset_hard(mds_role_t(role_selector.get_ns(), rank));
+    r = resetter.reset_hard();
   } else {
-    r = resetter.reset(mds_role_t(role_selector.get_ns(), rank));
+    r = resetter.reset();
   }
 
   return r;
index d3944144ddcf4693a98982655c0b009ee1998f7d..c31203f7369e4d31b646d645fb152478f39fdbc6 100644 (file)
@@ -37,6 +37,8 @@ class JournalTool : public MDSUtility
     // Bit hacky, use this `rank` member to control behaviour of the
     // various main_ functions.
     mds_rank_t rank;
+   
+    std::string type;
 
     // Entry points
     int main_journal(std::vector<const char*> &argv);
@@ -78,6 +80,8 @@ class JournalTool : public MDSUtility
         bufferlist *out_bl);
     int consume_inos(const std::set<inodeno_t> &inos);
 
+    //validate type
+    int validate_type(const std::string &type);
   public:
     void usage();
     JournalTool() :
index 32ada622982cacb4f436d634883bd531974495b1..cbc9a353ce1bacec0cc853ab0e9f88134d5820ff 100644 (file)
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_mds
 
-int Resetter::reset(mds_role_t role)
+int Resetter::init(mds_role_t role_, const std::string &type, bool hard)
+{
+  role = role_;
+  int r = MDSUtility::init();
+  if (r < 0) {
+    return r;
+  }
+
+  auto fs = fsmap->get_filesystem(role.fscid);
+  assert(nullptr != fs);
+
+  is_mdlog = false;
+  if (type == "mdlog") {
+    JournalPointer jp(role.rank, fs->mds_map.get_metadata_pool());
+    int rt = 0;
+    if (hard) {
+      jp.front = role.rank + MDS_INO_LOG_OFFSET;
+      jp.back = 0;
+      rt = jp.save(objecter);
+      if (rt != 0) {
+        derr << "Error writing journal pointer:  " << cpp_strerror(rt) << dendl;
+        return rt;
+      }
+      ino = jp.front; // only need to reset ino for mdlog
+    } else {
+      rt = jp.load(objecter);
+      if (rt != 0) {
+        std::cerr << "Error loading journal: " << cpp_strerror(rt) <<
+        ", pass --force to forcibly reset this journal" << std::endl;
+        return rt;
+      } else {
+        ino = jp.front;
+      }
+    }
+    is_mdlog = true;
+  } else if (type == "purge_queue") {
+    ino = MDS_INO_PURGE_QUEUE + role.rank;
+  } else {
+    ceph_abort(); // should not get here
+  }
+  return 0; 
+}
+
+int Resetter::reset()
 {
   Mutex mylock("Resetter::reset::lock");
   Cond cond;
@@ -35,18 +78,9 @@ int Resetter::reset(mds_role_t role)
 
   auto fs =  fsmap->get_filesystem(role.fscid);
   assert(fs != nullptr);
-  int64_t 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) <<
-      ", pass --force to forcibly reset this journal" << std::endl;
-    return jp_load_result;
-  }
 
-  Journaler journaler("resetter", jp.front,
-      pool_id,
+  Journaler journaler("resetter", ino,
+      fs->mds_map.get_metadata_pool(),
       CEPH_FS_ONDISK_MAGIC,
       objecter, 0, 0, &finisher);
 
@@ -101,34 +135,24 @@ int Resetter::reset(mds_role_t role)
   if (r != 0) {
     return r;
   }
-
-  r = _write_reset_event(&journaler);
-  if (r != 0) {
-    return r;
+  if (is_mdlog) {
+    r = _write_reset_event(&journaler); // reset envent is specific for mdlog journal
+    if (r != 0) {
+      return r;
+    }
   }
-
   cout << "done" << std::endl;
 
   return 0;
 }
 
-int Resetter::reset_hard(mds_role_t role)
+int Resetter::reset_hard()
 {
   auto fs =  fsmap->get_filesystem(role.fscid);
-  assert(fs != nullptr);
-  int64_t 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) {
-    derr << "Error writing journal pointer: " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  Journaler journaler("resetter", jp.front,
-    pool_id,
+  
+  Journaler journaler("resetter", ino,
+    fs->mds_map.get_metadata_pool(),
     CEPH_FS_ONDISK_MAGIC,
     objecter, 0, 0, &finisher);
   journaler.set_writeable();
@@ -142,23 +166,29 @@ int Resetter::reset_hard(mds_role_t role)
     Mutex::Locker l(lock);
     journaler.write_head(&cond);
   }
-  r = cond.wait();
+  
+  int r = cond.wait();
   if (r != 0) {
     derr << "Error writing journal header: " << cpp_strerror(r) << dendl;
     return r;
   }
-
+  
+  if (is_mdlog) // reset event is specific for mdlog journal
   {
     Mutex::Locker l(lock);
     r = _write_reset_event(&journaler);
+    if (r != 0) {
+      derr << "Error writing EResetJournal: " << cpp_strerror(r) << dendl;
+      return r;
+    }
   }
-  if (r != 0) {
-    derr << "Error writing EResetJournal: " << cpp_strerror(r) << dendl;
-    return r;
+  
+  if (is_mdlog) {
+    dout(4) << "Successfully wrote new journal pointer and header for rank "
+      << role << dendl;
+  } else {
+    dout(4) << "Successfully wrote header for rank " << role << dendl;
   }
-
-  dout(4) << "Successfully wrote new journal pointer and header for rank "
-    << role << dendl;
   return 0;
 }
 
index 115f6ffeecbcaee0126287c7686eb2200d3c76ff..6998e4598f4c73d8f3f9ec12630b3739bda71b9e 100644 (file)
@@ -26,18 +26,25 @@ class Journaler;
  * of the file to dump to.
  */
 class Resetter : public MDSUtility {
+private:
+  mds_role_t role;
+  inodeno_t ino;
+  bool is_mdlog;
+
 protected:
   int _write_reset_event(Journaler *journaler);
 
 public:
   Resetter() {}
+  ~Resetter() {}
 
+  int init(mds_role_t role_, const std::string &type, bool hard);
   /**
    * For use when no journal header/pointer was present: write one
    * out from scratch.
    */
-  int reset_hard(mds_role_t role);
-  int reset(mds_role_t role);
+  int reset_hard();
+  int reset();
 };
 
 #endif /* JOURNAL_RESETTER_H_ */