diff options
-rw-r--r-- | jstests/disk/wt_repair_corrupt_metadata.js | 39 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp | 28 |
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() { |