diff options
author | Keith Bostic <keith@wiredtiger.com> | 2016-03-27 12:47:02 -0400 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2016-03-27 12:47:02 -0400 |
commit | 45aa4385e43957970bfb8f768c63bf05afb5d5f8 (patch) | |
tree | d66a42e6b7cb812f0ac4f8a2c9662ea73152c6a0 /src/support/filename.c | |
parent | 69b26f1f8338eee18fe0abdba43264e4cbfd443f (diff) | |
download | mongo-45aa4385e43957970bfb8f768c63bf05afb5d5f8.tar.gz |
WT-2330: in-memory configurations should not create on-disk collection files
The wt utility isn't syncing the enclosing directory on a backup file
which leaves us potentially vulnerable on a crash on Linux. WiredTiger
knows how to do the magic, so use a WiredTiger function to do the backup
file copy. This also gets rid of some Windows-specific code in the wt
utility.
Diffstat (limited to 'src/support/filename.c')
-rw-r--r-- | src/support/filename.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/support/filename.c b/src/support/filename.c index ac0aee5686e..b4858d2e982 100644 --- a/src/support/filename.c +++ b/src/support/filename.c @@ -123,3 +123,69 @@ __wt_sync_handle_and_rename( return (__wt_rename_and_sync_directory(session, from, to)); } + +/* + * __wt_copy_and_sync -- + * Copy a file safely; here to support the wt utility. + */ +int +__wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to) +{ + WT_DECL_ITEM(tmp); + WT_DECL_RET; + WT_FH *ffh, *tfh; + WT_SESSION_IMPL *session; + size_t n; + wt_off_t offset, size; + char *buf; + + session = (WT_SESSION_IMPL *)wt_session; + ffh = tfh = NULL; + buf = NULL; + + /* + * Remove the target file if it exists, then create a temporary file, + * copy the original into it and rename it into place. I don't think + * its necessary to remove the file, or create a copy and do a rename, + * it's likely safe to overwrite the backup file directly. I'm doing + * the remove and rename to insulate us from errors in other programs + * that might not detect a corrupted backup file; it's cheap insurance + * in a path where undetected failure is very bad. + */ + WT_RET(__wt_remove_if_exists(session, to)); + + WT_ERR(__wt_scr_alloc(session, 0, &tmp)); + WT_ERR(__wt_buf_fmt(session, tmp, "%s.copy", to)); + + /* Open the from and temporary file handles. */ + WT_ERR(__wt_open(session, from, + WT_FILE_TYPE_REGULAR, WT_OPEN_READONLY, &ffh)); + WT_ERR(__wt_open(session, tmp->data, + WT_FILE_TYPE_REGULAR, WT_OPEN_CREATE | WT_OPEN_EXCLUSIVE, &tfh)); + + /* + * Allocate a copy buffer. Don't use a scratch buffer, this thing is + * big, and we don't want it hanging around. + */ +#define WT_BACKUP_COPY_SIZE (128 * 1024) + WT_ERR(__wt_malloc(session, WT_BACKUP_COPY_SIZE, &buf)); + + /* Get the file's size, then copy the bytes. */ + WT_ERR(__wt_filesize(session, ffh, &size)); + for (offset = 0; size > 0; size -= n, offset += n) { + n = (size_t)WT_MIN(size, WT_BACKUP_COPY_SIZE); + WT_ERR(__wt_read(session, ffh, offset, n, buf)); + WT_ERR(__wt_write(session, tfh, offset, n, buf)); + } + + /* Close the from handle, then swap the temporary file into place. */ + WT_ERR(__wt_close(session, &ffh)); + ret = __wt_sync_handle_and_rename(session, &tfh, tmp->data, to); + +err: WT_TRET(__wt_close(session, &ffh)); + WT_TRET(__wt_close(session, &tfh)); + + __wt_free(session, buf); + __wt_scr_free(session, &tmp); + return (ret); +} |