summaryrefslogtreecommitdiff
path: root/src/mongo/util
diff options
context:
space:
mode:
authoragherardi <alessandro.gherardi@yahoo.com>2014-12-28 18:34:43 -0700
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-01-09 13:08:02 -0500
commitaee446a97d7c3d7b6129348de6957d8e178864b2 (patch)
treec10b48378e1e4fa7538cec2cabf5e1cdc188204e /src/mongo/util
parentbc274534b82eb2328d417dc5b256fb6d66287f74 (diff)
downloadmongo-aee446a97d7c3d7b6129348de6957d8e178864b2.tar.gz
SERVER-14992: Checking ntfs.sys version to figure out if it's necessary to zero out data files.
Closes #894 Signed-off-by: Mark Benvenuto <mark.benvenuto@mongodb.com>
Diffstat (limited to 'src/mongo/util')
-rw-r--r--src/mongo/util/file_allocator.cpp45
-rw-r--r--src/mongo/util/processinfo_win32.cpp91
2 files changed, 134 insertions, 2 deletions
diff --git a/src/mongo/util/file_allocator.cpp b/src/mongo/util/file_allocator.cpp
index cf4be6ac080..319d6fddfd0 100644
--- a/src/mongo/util/file_allocator.cpp
+++ b/src/mongo/util/file_allocator.cpp
@@ -84,6 +84,18 @@ namespace mongo {
static inline long lseek(int fd, long offset, int origin) { return _lseek(fd, offset, origin); }
static inline int write(int fd, const void *data, int count) { return _write(fd, data, count); }
static inline int close(int fd) { return _close(fd); }
+
+ typedef BOOL (CALLBACK *GetVolumeInformationByHandleWPtr)(HANDLE, LPWSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR, DWORD);
+ GetVolumeInformationByHandleWPtr GetVolumeInformationByHandleWFunc;
+
+ MONGO_INITIALIZER(InitGetVolumeInformationByHandleW)(InitializerContext *context) {
+ HMODULE kernelLib = LoadLibraryA("kernel32.dll");
+ if (kernelLib) {
+ GetVolumeInformationByHandleWFunc = reinterpret_cast<GetVolumeInformationByHandleWPtr>
+ (GetProcAddress(kernelLib, "GetVolumeInformationByHandleW"));
+ }
+ return Status::OK();
+ }
#endif
boost::filesystem::path ensureParentDirCreated(const boost::filesystem::path& p){
@@ -195,6 +207,30 @@ namespace mongo {
#endif
}
+#if defined(_WIN32)
+ static bool isFileOnNTFSVolume(int fd) {
+ if (!GetVolumeInformationByHandleWFunc) {
+ warning() << "Could not retrieve pointer to GetVolumeInformationByHandleW function";
+ return false;
+ }
+
+ HANDLE fileHandle = (HANDLE)_get_osfhandle(fd);
+ if (fileHandle == INVALID_HANDLE_VALUE) {
+ warning() << "_get_osfhandle() failed with " << _strerror(NULL);
+ return false;
+ }
+
+ WCHAR fileSystemName[MAX_PATH + 1];
+ if (!GetVolumeInformationByHandleWFunc(fileHandle, NULL, 0, NULL, 0, NULL, fileSystemName, sizeof(fileSystemName))) {
+ DWORD gle = GetLastError();
+ warning() << "GetVolumeInformationByHandleW failed with " << errnoWithDescription(gle);
+ return false;
+ }
+
+ return lstrcmpW(fileSystemName, L"NTFS") == 0;
+ }
+#endif
+
void FileAllocator::ensureLength(int fd , long size) {
// Test running out of disk scenarios
if (MONGO_FAIL_POINT(allocateDiskFull)) {
@@ -240,6 +276,13 @@ namespace mongo {
return;
}
+#if defined(_WIN32)
+ if (!isFileOnNTFSVolume(fd)) {
+ log() << "No need to zero out datafile on non-NTFS volume" << endl;
+ return;
+ }
+#endif
+
lseek(fd, 0, SEEK_SET);
const long z = 256 * 1024;
@@ -301,7 +344,7 @@ namespace mongo {
return fn;
}
return "";
- }
+ }
void FileAllocator::run( FileAllocator * fa ) {
setThreadName( "FileAllocator" );
diff --git a/src/mongo/util/processinfo_win32.cpp b/src/mongo/util/processinfo_win32.cpp
index 2cc68e7c808..7edbd649713 100644
--- a/src/mongo/util/processinfo_win32.cpp
+++ b/src/mongo/util/processinfo_win32.cpp
@@ -121,6 +121,89 @@ namespace mongo {
#endif
}
+ bool getFileVersion(const char *filePath, DWORD &fileVersionMS, DWORD &fileVersionLS) {
+ DWORD verSize = GetFileVersionInfoSizeA(filePath, NULL);
+ if (verSize == 0) {
+ DWORD gle = GetLastError();
+ warning() << "GetFileVersionInfoSizeA on " << filePath << " failed with " << errnoWithDescription(gle);
+ return false;
+ }
+
+ boost::scoped_array<char> verData(new char[verSize]);
+ if (GetFileVersionInfoA(filePath, NULL, verSize, verData.get()) == 0) {
+ DWORD gle = GetLastError();
+ warning() << "GetFileVersionInfoSizeA on " << filePath << " failed with " << errnoWithDescription(gle);
+ return false;
+ }
+
+ UINT size;
+ VS_FIXEDFILEINFO *verInfo;
+ if (VerQueryValueA(verData.get(), "\\", (LPVOID *)&verInfo, &size) == 0) {
+ DWORD gle = GetLastError();
+ warning() << "VerQueryValueA on " << filePath << " failed with " << errnoWithDescription(gle);
+ return false;
+ }
+
+ if (size != sizeof(VS_FIXEDFILEINFO)) {
+ warning() << "VerQueryValueA on " << filePath << " returned structure with unexpected size";
+ return false;
+ }
+
+ fileVersionMS = verInfo->dwFileVersionMS;
+ fileVersionLS = verInfo->dwFileVersionLS;
+ return true;
+ }
+
+ // If the version of the ntfs.sys driver shows that the KB2731284 hotfix or a later update
+ // is installed, zeroing out data files is unnecessary. The file version numbers used below
+ // are taken from the Hotfix File Information at http://support.microsoft.com/kb/2731284.
+ bool isKB2731284OrLaterUpdateInstalled() {
+ UINT pathBufferSize = GetSystemDirectoryA(NULL, 0);
+ if (pathBufferSize == 0) {
+ DWORD gle = GetLastError();
+ warning() << "GetSystemDirectoryA failed with " << errnoWithDescription(gle);
+ return false;
+ }
+
+ boost::scoped_array<char> systemDirectory(new char[pathBufferSize]);
+ UINT systemDirectoryPathLen;
+ systemDirectoryPathLen = GetSystemDirectoryA(systemDirectory.get(), pathBufferSize);
+ if (systemDirectoryPathLen == 0) {
+ DWORD gle = GetLastError();
+ warning() << "GetSystemDirectoryA failed with " << errnoWithDescription(gle);
+ return false;
+ }
+
+ if (systemDirectoryPathLen != pathBufferSize - 1) {
+ warning() << "GetSystemDirectoryA returned unexpected path length";
+ return false;
+ }
+
+ string ntfsDotSysPath = systemDirectory.get();
+ if (ntfsDotSysPath.back() != '\\') {
+ ntfsDotSysPath.append("\\");
+ }
+ ntfsDotSysPath.append("drivers\\ntfs.sys");
+ DWORD fileVersionMS;
+ DWORD fileVersionLS;
+ if (getFileVersion(ntfsDotSysPath.c_str(), fileVersionMS, fileVersionLS)) {
+ WORD fileVersionFirstNumber = HIWORD(fileVersionMS);
+ WORD fileVersionSecondNumber = LOWORD(fileVersionMS);
+ WORD fileVersionThirdNumber = HIWORD(fileVersionLS);
+ WORD fileVersionFourthNumber = LOWORD(fileVersionLS);
+
+ if (fileVersionFirstNumber == 6 && fileVersionSecondNumber == 1 && fileVersionThirdNumber == 7600 &&
+ fileVersionFourthNumber >= 21296 && fileVersionFourthNumber <= 21999) {
+ return true;
+ } else if (fileVersionFirstNumber == 6 && fileVersionSecondNumber == 1 && fileVersionThirdNumber == 7601 &&
+ fileVersionFourthNumber >= 22083 && fileVersionFourthNumber <= 22999) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
void ProcessInfo::SystemInfo::collectSystemInfo() {
BSONObjBuilder bExtra;
stringstream verstr;
@@ -179,7 +262,13 @@ namespace mongo {
// http://support.microsoft.com/kb/2731284.
//
if ((osvi.wServicePackMajor >= 0) && (osvi.wServicePackMajor < 2)) {
- fileZeroNeeded = true;
+ if (isKB2731284OrLaterUpdateInstalled()) {
+ log() << "Hotfix KB2731284 or later update is installed, no need to zero-out data files";
+ fileZeroNeeded = false;
+ } else {
+ log() << "Hotfix KB2731284 or later update is not installed, will zero-out data files";
+ fileZeroNeeded = true;
+ }
}
break;
case 0: