From: Gu Zhongyan Date: Mon, 21 May 2018 07:00:38 +0000 (+0800) Subject: cephfs-journal-tool: check fsid when import purge queue X-Git-Tag: v14.0.1~970^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e0eef2aab10747de0efc128133c567204b4d0322;p=ceph.git cephfs-journal-tool: check fsid when import purge queue import purge queue will triger file delete in cluster. we occasionally imported a purge queue from one production cluster to a test cluster and found the the fs in test cluster was damaged because some objects are really delted as its inode recorded in purge queue. add fsid when exporting purge queue, check if the fsid matched when importing purge queue. This could make cephfs-journal-tool safer to handle purge queue issues. Signed-off-by: Gu Zhongyan Signed-off-by: yupeng chen chenyupeng-it@360.cn --- diff --git a/src/tools/cephfs/Dumper.cc b/src/tools/cephfs/Dumper.cc index 67252eaa326f..9a35eb152bd3 100644 --- a/src/tools/cephfs/Dumper.cc +++ b/src/tools/cephfs/Dumper.cc @@ -25,6 +25,7 @@ #include "mds/LogEvent.h" #include "mds/JournalPointer.h" #include "osdc/Journaler.h" +#include "mon/MonClient.h" #include "Dumper.h" @@ -106,15 +107,19 @@ int Dumper::dump(const char *dump_file) int fd = ::open(dump_file, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (fd >= 0) { // include an informative header + uuid_d fsid = monc->get_fsid(); + char fsid_str[40]; + fsid.print(fsid_str); char buf[HEADER_LEN]; memset(buf, 0, sizeof(buf)); - snprintf(buf, HEADER_LEN, "Ceph mds%d journal dump\n start offset %llu (0x%llx)\n length %llu (0x%llx)\n write_pos %llu (0x%llx)\n format %llu\n trimmed_pos %llu (0x%llx)\n%c", + snprintf(buf, HEADER_LEN, "Ceph mds%d journal dump\n start offset %llu (0x%llx)\n length %llu (0x%llx)\n write_pos %llu (0x%llx)\n format %llu\n trimmed_pos %llu (0x%llx)\n fsid %s\n%c", role.rank, (unsigned long long)start, (unsigned long long)start, (unsigned long long)len, (unsigned long long)len, (unsigned long long)journaler.last_committed.write_pos, (unsigned long long)journaler.last_committed.write_pos, (unsigned long long)journaler.last_committed.stream_format, (unsigned long long)journaler.last_committed.trimmed_pos, (unsigned long long)journaler.last_committed.trimmed_pos, + fsid_str, 4); r = safe_write(fd, buf, sizeof(buf)); if (r) { @@ -185,7 +190,7 @@ int Dumper::dump(const char *dump_file) } } -int Dumper::undump(const char *dump_file) +int Dumper::undump(const char *dump_file, bool force) { cout << "undump " << dump_file << std::endl; @@ -216,6 +221,33 @@ int Dumper::undump(const char *dump_file) sscanf(strstr(buf, "length"), "length %llu", &len); sscanf(strstr(buf, "write_pos"), "write_pos %llu", &write_pos); sscanf(strstr(buf, "format"), "format %llu", &format); + + if (!force) { + // need to check if fsid match onlien cluster fsid + if (strstr(buf, "fsid")) { + uuid_d fsid; + char fsid_str[40]; + sscanf(strstr(buf, "fsid"), "fsid %s", fsid_str); + r = fsid.parse(fsid_str); + if (!r) { + derr << "Invalid fsid" << dendl; + ::close(fd); + return -EINVAL; + } + + if (fsid != monc->get_fsid()) { + derr << "Imported journal fsid does not match online cluster fsid" << dendl; + derr << "Use --force to skip fsid check" << dendl; + ::close(fd); + return -EINVAL; + } + } else { + derr << "Invalid header, no fsid embeded" << dendl; + ::close(fd); + return -EINVAL; + } + } + if (strstr(buf, "trimmed_pos")) { sscanf(strstr(buf, "trimmed_pos"), "trimmed_pos %llu", &trimmed_pos); } else { diff --git a/src/tools/cephfs/Dumper.h b/src/tools/cephfs/Dumper.h index aad7b3e10a59..758f3cdea0f0 100644 --- a/src/tools/cephfs/Dumper.h +++ b/src/tools/cephfs/Dumper.h @@ -39,7 +39,7 @@ public: 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); + int undump(const char *dumpfile, bool force); }; #endif /* JOURNAL_DUMPER_H_ */ diff --git a/src/tools/cephfs/JournalTool.cc b/src/tools/cephfs/JournalTool.cc index 3e746de95859..30ee369c2a7a 100644 --- a/src/tools/cephfs/JournalTool.cc +++ b/src/tools/cephfs/JournalTool.cc @@ -45,7 +45,7 @@ void JournalTool::usage() << " cephfs-journal-tool [options] journal \n" << " :\n" << " inspect\n" - << " import \n" + << " import [--force]\n" << " export \n" << " reset [--force]\n" << " cephfs-journal-tool [options] header \n" @@ -202,9 +202,18 @@ int JournalTool::main_journal(std::vector &argv) if (command == "inspect") { return journal_inspect(); } else if (command == "export" || command == "import") { + bool force = false; if (argv.size() >= 2) { std::string const path = argv[1]; - return journal_export(path, command == "import"); + if (argv.size() == 3) { + if (std::string(argv[2]) == "--force") { + force = true; + } else { + std::cerr << "Unknown argument " << argv[1] << std::endl; + return -EINVAL; + } + } + return journal_export(path, command == "import", force); } else { derr << "Missing path" << dendl; return -EINVAL; @@ -552,7 +561,7 @@ int JournalTool::journal_inspect() * back to manually listing RADOS objects and extracting them, which * they can do with the ``rados`` CLI. */ -int JournalTool::journal_export(std::string const &path, bool import) +int JournalTool::journal_export(std::string const &path, bool import, bool force) { int r = 0; JournalScanner js(input, rank, type); @@ -584,7 +593,7 @@ int JournalTool::journal_export(std::string const &path, bool import) return r; } if (import) { - r = dumper.undump(path.c_str()); + r = dumper.undump(path.c_str(), force); } else { r = dumper.dump(path.c_str()); } diff --git a/src/tools/cephfs/JournalTool.h b/src/tools/cephfs/JournalTool.h index 3d1188222cb7..87f37691ae22 100644 --- a/src/tools/cephfs/JournalTool.h +++ b/src/tools/cephfs/JournalTool.h @@ -50,7 +50,7 @@ class JournalTool : public MDSUtility // Journal operations int journal_inspect(); - int journal_export(std::string const &path, bool import); + int journal_export(std::string const &path, bool import, bool force); int journal_reset(bool hard); // Header operations