summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Williams <louis.williams@mongodb.com>2018-11-02 12:13:32 -0400
committerLouis Williams <louis.williams@mongodb.com>2018-11-29 11:59:09 -0500
commit94d69adc58b1c09e04c6162b578bb3c43bf66abc (patch)
tree866ceceb4b461a22900555616899f550e31c19a0
parent86ff4e64743a2772cc279e02841b61f71ef8a031 (diff)
downloadmongo-94d69adc58b1c09e04c6162b578bb3c43bf66abc.tar.gz
SERVER-37796 Always salvage WiredTiger metadata regardless of error code when starting with repair
(cherry picked from commit c7553b861796c1581c85b3cbc4e55dcc9666aa0f) (cherry picked from commit eae0b57705a7b18362b7028c6fcb7c2469043ef4) (cherry picked from commit 13950ba0c4dfe22de28d1a7ec724d102ad69b949)
-rw-r--r--jstests/disk/wt_repair_corrupt_metadata.js39
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp28
2 files changed, 53 insertions, 14 deletions
diff --git a/jstests/disk/wt_repair_corrupt_metadata.js b/jstests/disk/wt_repair_corrupt_metadata.js
index 16c12ac9bd7..a8240e97fe0 100644
--- a/jstests/disk/wt_repair_corrupt_metadata.js
+++ b/jstests/disk/wt_repair_corrupt_metadata.js
@@ -26,7 +26,8 @@
// Unfortunately using --nojournal triggers a WT_PANIC and aborts in debug builds, which the
// following test case can exercise.
// TODO: This return can be removed once WT-4310 is completed.
- if (db.adminCommand('buildInfo').debug && mongodOptions.hasOwnProperty('nojournal')) {
+ let isDebug = db.adminCommand('buildInfo').debug;
+ if (isDebug && mongodOptions.hasOwnProperty('nojournal')) {
jsTestLog(
"Skipping test case because this is a debug build and --nojournal was provided.");
return;
@@ -65,13 +66,47 @@
mongod = startMongodOnExistingPath(dbpath, mongodOptions);
testColl = mongod.getDB(baseName)[collName];
- // The collection exists depite using an older turtle file because salvage is able to find
+ // The collection exists despite using an older turtle file because salvage is able to find
// the table in the WiredTiger.wt file.
assert(testColl.exists());
// We can assert that the data exists because the salvage only took place on the metadata,
// not the data.
assert.eq(testColl.find({}).itcount(), 1);
MongoRunner.stopMongod(mongod);
+
+ // Corrupt the .turtle file in a very specific way such that the log sequence numbers are
+ // invalid.
+ if (mongodOptions.hasOwnProperty('journal')) {
+ // TODO: This return can be removed once WT-4459 is completed.
+ if (_isAddressSanitizerActive()) {
+ jsTestLog("Skipping log file corruption because the address sanitizer is active.");
+ return;
+ }
+
+ jsTestLog("Corrupting log file metadata");
+
+ let data = cat(turtleFile, true /* useBinaryMode */);
+ let re = /checkpoint_lsn=\(([0-9,]+)\)/g;
+ let newData = data.replace(re, "checkpoint_lsn=(1,2)");
+
+ print('writing data to new turtle file: \n' + newData);
+ removeFile(turtleFile);
+ writeFile(turtleFile, newData, true /* useBinaryMode */);
+
+ assertRepairSucceeds(dbpath, mongod.port, mongodOptions);
+
+ mongod = startMongodOnExistingPath(dbpath, mongodOptions);
+ testColl = mongod.getDB(baseName)[collName];
+
+ // The collection exists despite using a salvaged turtle file because salvage is able to
+ // find the table in the WiredTiger.wt file.
+ assert(testColl.exists());
+
+ // We can assert that the data exists because the salvage only took place on the
+ // metadata, not the data.
+ assert.eq(testColl.find({}).itcount(), 1);
+ MongoRunner.stopMongod(mongod);
+ }
};
// Repair may behave differently with journaling enabled or disabled, but the end result should
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp
index edf280200c0..fbd5f6ad3fe 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp
@@ -631,22 +631,26 @@ void WiredTigerKVEngine::_openWiredTiger(const std::string& path, const std::str
severe() << kWTRepairMsg;
fassertFailedNoTrace(50944);
}
+ }
- warning() << "Attempting to salvage WiredTiger metadata";
- configStr = wtOpenConfig + ",salvage=true";
- ret = wiredtiger_open(path.c_str(), wtEventHandler, configStr.c_str(), &_conn);
- if (!ret) {
- StorageRepairObserver::get(getGlobalServiceContext())
- ->onModification("WiredTiger metadata salvaged");
- return;
- }
+ severe() << "Reason: " << wtRCToStatus(ret).reason();
+ if (!_inRepairMode) {
+ fassertFailedNoTrace(28595);
+ }
- severe() << "Failed to salvage WiredTiger metadata: " + wtRCToStatus(ret).reason();
- fassertFailedNoTrace(50947);
+ // Always attempt to salvage metadata regardless of error code when in repair mode.
+
+ warning() << "Attempting to salvage WiredTiger metadata";
+ configStr = wtOpenConfig + ",salvage=true";
+ ret = wiredtiger_open(path.c_str(), wtEventHandler, configStr.c_str(), &_conn);
+ if (!ret) {
+ StorageRepairObserver::get(getGlobalServiceContext())
+ ->onModification("WiredTiger metadata salvaged");
+ return;
}
- severe() << "Reason: " << wtRCToStatus(ret).reason();
- fassertFailedNoTrace(28595);
+ severe() << "Failed to salvage WiredTiger metadata: " + wtRCToStatus(ret).reason();
+ fassertFailedNoTrace(50947);
}
void WiredTigerKVEngine::cleanShutdown() {