From fc1d6da713fa334800d3e1c9e33e34edfae6c47e Mon Sep 17 00:00:00 2001 From: John Spray Date: Mon, 12 May 2014 18:39:33 +0100 Subject: [PATCH] tools/cephfs: Update for JournalPointer Signed-off-by: John Spray --- src/tools/cephfs/JournalScanner.cc | 88 +++++++++++++++++++++++++----- src/tools/cephfs/JournalScanner.h | 11 +++- src/tools/cephfs/JournalTool.cc | 10 ++-- src/tools/cephfs/JournalTool.h | 3 +- 4 files changed, 91 insertions(+), 21 deletions(-) diff --git a/src/tools/cephfs/JournalScanner.cc b/src/tools/cephfs/JournalScanner.cc index 3eb482d4bf9bd..304b9c0ac4e20 100644 --- a/src/tools/cephfs/JournalScanner.cc +++ b/src/tools/cephfs/JournalScanner.cc @@ -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; } diff --git a/src/tools/cephfs/JournalScanner.h b/src/tools/cephfs/JournalScanner.h index 8e579a0862627..2700f2b14872c 100644 --- a/src/tools/cephfs/JournalScanner.h +++ b/src/tools/cephfs/JournalScanner.h @@ -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 EventMap; typedef std::pair Range; + bool pointer_present; + bool pointer_valid; bool header_present; bool header_valid; Journaler::Header *header; diff --git a/src/tools/cephfs/JournalTool.cc b/src/tools/cephfs/JournalTool.cc index 8b668148b4458..d01e9989b52cb 100644 --- a/src/tools/cephfs/JournalTool.cc +++ b/src/tools/cephfs/JournalTool.cc @@ -232,7 +232,7 @@ int JournalTool::main_header(std::vector &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 &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 &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); diff --git a/src/tools/cephfs/JournalTool.h b/src/tools/cephfs/JournalTool.h index 96683b78c6c3a..1c5745493f955 100644 --- a/src/tools/cephfs/JournalTool.h +++ b/src/tools/cephfs/JournalTool.h @@ -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(); -- 2.39.5