diff options
author | agherardi <alessandro.gherardi@yahoo.com> | 2014-12-28 18:34:43 -0700 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2015-01-09 13:08:02 -0500 |
commit | aee446a97d7c3d7b6129348de6957d8e178864b2 (patch) | |
tree | c10b48378e1e4fa7538cec2cabf5e1cdc188204e /src/mongo/util | |
parent | bc274534b82eb2328d417dc5b256fb6d66287f74 (diff) | |
download | mongo-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.cpp | 45 | ||||
-rw-r--r-- | src/mongo/util/processinfo_win32.cpp | 91 |
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: |