summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith.bostic@mongodb.com>2017-03-23 02:27:54 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2017-03-23 17:27:54 +1100
commit6bd63027a6fd00db3f0f379acb929c22cd1b7f6f (patch)
treeaebe2e6583dee65925e826d24164d269ecb20c7d
parent620398dc9a90b401aa9e4437c834bfbb2a6d9a6d (diff)
downloadmongo-6bd63027a6fd00db3f0f379acb929c22cd1b7f6f.tar.gz
SERVER-28194 Missing WiredTiger.turtle file loses data (#3337)
There's a two step process on Windows to rename files (including the turtle file), remove the original and then move the replacement into place -- a DeleteFileW followed by a MoveFileW. If we crash in the middle (and in SERVER-28194, it looks like there's a weirder failure mode, where the DeleteFileW succeeded, but the file was still there), we can be left without a turtle file, which will lose all of the data in the database. * Add the MOVEFILE_WRITE_THROUGH flag to the MoveFileEx call. If we somehow end up in a copy-then-delete path, that flag adds a disk flush after the copy phase, so the window of vulnerability is as short as possible.
-rw-r--r--dist/s_string.ok5
-rw-r--r--src/os_win/os_fs.c23
2 files changed, 13 insertions, 15 deletions
diff --git a/dist/s_string.ok b/dist/s_string.ok
index 39b6b163cd9..1f7f7d9fd3a 100644
--- a/dist/s_string.ok
+++ b/dist/s_string.ok
@@ -225,8 +225,10 @@ MEMALIGN
MERCHANTABILITY
METADATA
MONGODB
+MOVEFILE
MRXB
MRXBOPC
+MSDN
MSVC
MULTI
MULTIBLOCK
@@ -240,8 +242,7 @@ Metadata
Mewhort
Mitzenmacher
MongoDB
-MoveFile
-MoveFileW
+MoveFileExW
Multi
MultiByteToWideChar
Multithreaded
diff --git a/src/os_win/os_fs.c b/src/os_win/os_fs.c
index 2f76fff04a5..5cf47ea5763 100644
--- a/src/os_win/os_fs.c
+++ b/src/os_win/os_fs.c
@@ -87,22 +87,19 @@ __win_fs_rename(WT_FILE_SYSTEM *file_system,
WT_ERR(__wt_to_utf16_string(session, to, &to_wide));
/*
- * Check if file exists since Windows does not override the file if
- * it exists.
+ * We want an atomic rename, but that's not guaranteed by MoveFileExW
+ * (or by any MSDN API). Don't set the MOVEFILE_COPY_ALLOWED flag to
+ * prevent the system from falling back to a copy and delete process.
+ * Do set the MOVEFILE_WRITE_THROUGH flag so the window is as small
+ * as possible, just in case. WiredTiger renames are done in a single
+ * directory and we expect that to be an atomic metadata update on any
+ * modern filesystem.
*/
- if (GetFileAttributesW(to_wide->data) != INVALID_FILE_ATTRIBUTES)
- if (DeleteFileW(to_wide->data) == FALSE) {
- windows_error = __wt_getlasterror();
- __wt_errx(session,
- "%s: file-rename: DeleteFileW: %s",
- to, __wt_formatmessage(session, windows_error));
- WT_ERR(__wt_map_windows_error(windows_error));
- }
-
- if (MoveFileW(from_wide->data, to_wide->data) == FALSE) {
+ if (MoveFileExW(from_wide->data, to_wide->data,
+ MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == FALSE) {
windows_error = __wt_getlasterror();
__wt_errx(session,
- "%s to %s: file-rename: MoveFileW: %s",
+ "%s to %s: file-rename: MoveFileExW: %s",
from, to, __wt_formatmessage(session, windows_error));
WT_ERR(__wt_map_windows_error(windows_error));
}