]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs: Update for JournalPointer
authorJohn Spray <john.spray@inktank.com>
Mon, 12 May 2014 17:39:33 +0000 (18:39 +0100)
committerJohn Spray <john.spray@inktank.com>
Tue, 20 May 2014 13:07:51 +0000 (14:07 +0100)
Signed-off-by: John Spray <john.spray@inktank.com>
src/tools/cephfs/JournalScanner.cc
src/tools/cephfs/JournalScanner.h
src/tools/cephfs/JournalTool.cc
src/tools/cephfs/JournalTool.h

index 3eb482d4bf9bd5d79cff196fde2a27d6d534ba2c..304b9c0ac4e2035b846d7333052c7ebcf9aa3f79 100644 (file)
@@ -13,6 +13,7 @@
 
 
 #include "include/rados/librados.hpp"
+#include "mds/JournalPointer.h"
 
 #include "JournalScanner.h"
 
@@ -29,11 +30,19 @@ int JournalScanner::scan(bool const full)
 {
   int r = 0;
 
-  r = scan_header();
+  r = scan_pointer();
   if (r < 0) {
     return r;
   }
-  if (full) {
+
+  if (pointer_present) {
+    r = scan_header();
+    if (r < 0) {
+      return r;
+    }
+  }
+
+  if (full && header_present) {
     r = scan_events();
     if (r < 0) {
       return r;
@@ -43,12 +52,47 @@ int JournalScanner::scan(bool const full)
   return 0;
 }
 
+
+int JournalScanner::scan_pointer()
+{
+  // Issue read
+  std::string const pointer_oid = obj_name(MDS_INO_LOG_POINTER_OFFSET + rank, 0);
+  bufferlist pointer_bl;
+  int r = io.read(pointer_oid, pointer_bl, INT_MAX, 0);
+  if (r == -ENOENT) {
+    // 'Successfully' discovered the pointer is missing.
+    derr << "Pointer " << pointer_oid << " is absent" << dendl;
+    return 0;
+  } else if (r < 0) {
+    // Error preventing us interrogating pointer
+    derr << "Pointer " << pointer_oid << " is unreadable" << dendl;
+    return r;
+  } else {
+    dout(4) << "Pointer " << pointer_oid << " is readable" << dendl;
+    pointer_present = true;
+
+    JournalPointer jp;
+    try {
+      bufferlist::iterator q = pointer_bl.begin();
+      jp.decode(q);
+    } catch(buffer::error e) {
+      derr << "Pointer " << pointer_oid << " is corrupt: " << e.what() << dendl;
+      return 0;
+    }
+
+    pointer_valid = true;
+    ino = jp.front;
+    return 0;
+  }
+}
+
+
 int JournalScanner::scan_header()
 {
   int r;
 
   bufferlist header_bl;
-  std::string header_name = obj_name(0, rank);
+  std::string header_name = obj_name(0);
   dout(4) << "JournalScanner::scan: reading header object '" << header_name << "'" << dendl;
   r = io.read(header_name, header_bl, INT_MAX, 0);
   if (r < 0) {
@@ -110,7 +154,7 @@ int JournalScanner::scan_events()
   for (uint64_t obj_offset = (read_offset / object_size); ; obj_offset++) {
     // Read this journal segment
     bufferlist this_object;
-    std::string const oid = obj_name(obj_offset, rank);
+    std::string const oid = obj_name(obj_offset);
     r = io.read(oid, this_object, INT_MAX, 0);
 
     // Handle absent journal segments
@@ -258,7 +302,10 @@ JournalScanner::~JournalScanner()
  */
 bool JournalScanner::is_healthy() const
 {
-  return (header_present && header_valid && ranges_invalid.empty() && objects_missing.empty());
+  return (pointer_present && pointer_valid
+      && header_present && header_valid
+      && ranges_invalid.empty()
+      && objects_missing.empty());
 }
 
 
@@ -272,27 +319,40 @@ bool JournalScanner::is_readable() const
 
 
 /**
- * Calculate the object name for a given offset in a particular MDS's journal
+ * Calculate the object name for a given offset
  */
-std::string JournalScanner::obj_name(uint64_t offset, int const rank)
+std::string JournalScanner::obj_name(inodeno_t ino, uint64_t offset) const
 {
-  char header_name[60];
-  snprintf(header_name, sizeof(header_name), "%llx.%08llx",
-      (unsigned long long)(MDS_INO_LOG_OFFSET + rank),
+  char name[60];
+  snprintf(name, sizeof(name), "%llx.%08llx",
+      (unsigned long long)(ino),
       (unsigned long long)offset);
-  return std::string(header_name);
+  return std::string(name);
+}
+
+
+std::string JournalScanner::obj_name(uint64_t offset) const
+{
+  return obj_name(ino, offset);
 }
 
 
+/*
+ * Write a human readable summary of the journal health
+ */
 void JournalScanner::report(std::ostream &out) const
 {
   out << "Overall journal integrity: " << (is_healthy() ? "OK" : "DAMAGED") << std::endl;
 
-  if (!header_present) {
-    out << "Header not found" << std::endl;
+  if (!pointer_present) {
+    out << "Pointer not found" << std::endl;
+  } else if (!pointer_valid) {
+    out << "Pointer could not be decoded" << std::endl;
   }
 
-  if (header_present && !header_valid) {
+  if (!header_present) {
+    out << "Header not found" << std::endl;
+  } else if (!header_valid) {
     out << "Header could not be decoded" << std::endl;
   }
 
index 8e579a086262740ae1e2de9234d5113c6feab33e..2700f2b14872ce986e7c0923befc673a523dd16b 100644 (file)
@@ -48,6 +48,8 @@ class JournalScanner
     io(io_),
     rank(rank_),
     filter(filter_),
+    pointer_present(false),
+    pointer_valid(false),
     header_present(false),
     header_valid(false),
     header(NULL) {};
@@ -57,6 +59,8 @@ class JournalScanner
       int rank_) :
     io(io_),
     rank(rank_),
+    pointer_present(false),
+    pointer_valid(false),
     header_present(false),
     header_valid(false),
     header(NULL) {};
@@ -64,13 +68,16 @@ class JournalScanner
   ~JournalScanner();
 
   int scan(bool const full=true);
+  int scan_pointer();
   int scan_header();
   int scan_events();
   void report(std::ostream &out) const;
 
-  static std::string obj_name(uint64_t offset, int const rank);
+  std::string obj_name(uint64_t offset) const;
+  std::string obj_name(inodeno_t ino, uint64_t offset) const;
 
   // The results of the scan
+  inodeno_t ino;  // Corresponds to JournalPointer.front
   class EventRecord {
     public:
     EventRecord() : log_event(NULL), raw_size(0) {}
@@ -80,6 +87,8 @@ class JournalScanner
   };
   typedef std::map<uint64_t, EventRecord> EventMap;
   typedef std::pair<uint64_t, uint64_t> Range;
+  bool pointer_present;
+  bool pointer_valid;
   bool header_present;
   bool header_valid;
   Journaler::Header *header;
index 8b668148b445813b252a395c83b0ebdf8c5561ce..d01e9989b52cbbb05bb66cba57d30d69b6de681f 100644 (file)
@@ -232,7 +232,7 @@ int JournalTool::main_header(std::vector<const char*> &argv)
     dout(4) << "Writing object..." << dendl;
     bufferlist header_bl;
     ::encode(*(js.header), header_bl);
-    io.write_full(JournalScanner::obj_name(0, rank), header_bl);
+    io.write_full(js.obj_name(0), header_bl);
     dout(4) << "Write complete." << dendl;
     std::cout << "Successfully updated header." << std::endl;
   } else {
@@ -341,7 +341,7 @@ int JournalTool::main_event(std::vector<const char*> &argv)
     if (filter.get_range(start, end)) {
       // Special case for range filter: erase a numeric range in the log
       uint64_t range = end - start;
-      int r = erase_region(start, range);
+      int r = erase_region(js, start, range);
       if (r) {
         derr << "Failed to erase region 0x" << std::hex << start << "~0x" << range << std::dec
              << ": " << cpp_strerror(r) << dendl;
@@ -352,7 +352,7 @@ int JournalTool::main_event(std::vector<const char*> &argv)
       for (JournalScanner::EventMap::iterator i = js.events.begin(); i != js.events.end(); ++i) {
         dout(4) << "Erasing offset 0x" << std::hex << i->first << std::dec << dendl;
 
-        int r = erase_region(i->first, i->second.raw_size);
+        int r = erase_region(js, i->first, i->second.raw_size);
         if (r) {
           derr << "Failed to erase event 0x" << std::hex << i->first << std::dec
                << ": " << cpp_strerror(r) << dendl;
@@ -647,7 +647,7 @@ int JournalTool::replay_offline(EMetaBlob &metablob, bool const dry_run)
  * Erase a region of the log by overwriting it with ENoOp
  *
  */
-int JournalTool::erase_region(uint64_t const pos, uint64_t const length)
+int JournalTool::erase_region(JournalScanner const &js, uint64_t const pos, uint64_t const length)
 {
   // To erase this region, we use our preamble, the encoding overhead
   // of an ENoOp, and our trailing start ptr.  Calculate how much padding
@@ -692,7 +692,7 @@ int JournalTool::erase_region(uint64_t const pos, uint64_t const length)
   uint64_t obj_offset = (pos / object_size);
   int r = 0;
   while(log_data.length()) {
-    std::string const oid = JournalScanner::obj_name(obj_offset, rank);
+    std::string const oid = js.obj_name(obj_offset);
     uint32_t offset_in_obj = write_offset % object_size;
     uint32_t write_len = min(log_data.length(), object_size - offset_in_obj);
 
index 96683b78c6c3a79d7cb625a8c667fbb5aeb1a57a..1c5745493f9551e80c5989e76b76e07da87c4ec5 100644 (file)
@@ -22,6 +22,7 @@
 #include "JournalFilter.h"
 
 class EMetaBlob;
+class JournalScanner;
 
 
 /**
@@ -57,7 +58,7 @@ class JournalTool : public MDSUtility
     int replay_offline(EMetaBlob &metablob, bool const dry_run);
 
     // Splicing
-    int erase_region(uint64_t const pos, uint64_t const length);
+    int erase_region(JournalScanner const &jp, uint64_t const pos, uint64_t const length);
 
   public:
     void usage();