diff options
Diffstat (limited to 'src/log/log.c')
-rw-r--r-- | src/log/log.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/src/log/log.c b/src/log/log.c index ca0b81c4cf6..efe4d22eeca 100644 --- a/src/log/log.c +++ b/src/log/log.c @@ -357,6 +357,67 @@ __wt_log_extract_lognum( } /* + * __log_zero -- + * Zero a log file. + */ +static int +__log_zero(WT_SESSION_IMPL *session, + WT_FH *fh, wt_off_t start_off, wt_off_t len) +{ + WT_CONNECTION_IMPL *conn; + WT_DECL_ITEM(zerobuf); + WT_DECL_RET; + WT_LOG *log; + uint32_t allocsize, bufsz, off, partial, wrlen; + + conn = S2C(session); + log = conn->log; + allocsize = log->allocsize; + zerobuf = NULL; + if (allocsize < WT_MEGABYTE) + bufsz = WT_MEGABYTE; + else + bufsz = allocsize; + /* + * If they're using smaller log files, cap it at the file size. + */ + if (conn->log_file_max < bufsz) + bufsz = (uint32_t)conn->log_file_max; + WT_RET(__wt_scr_alloc(session, bufsz, &zerobuf)); + memset(zerobuf->mem, 0, zerobuf->memsize); + WT_STAT_FAST_CONN_INCR(session, log_zero_fills); + + /* + * Read in a chunk starting at the end of the file. Keep going until + * we reach the beginning or we find a chunk that contains any non-zero + * bytes. Compare against a known zero byte chunk. + */ + off = (uint32_t)start_off; + while (off < (uint32_t)len) { + /* + * Typically we start to zero the file after the log header + * and the bufsz is a sector-aligned size. So we want to + * align our writes when we can. + */ + partial = off % bufsz; + if (partial != 0) + wrlen = bufsz - partial; + else + wrlen = bufsz; + /* + * Check if we're writing a partial amount at the end too. + */ + if ((uint32_t)len - off < bufsz) + wrlen = (uint32_t)len - off; + WT_ERR(__wt_write(session, + fh, (wt_off_t)off, wrlen, zerobuf->mem)); + off += wrlen; + } +err: __wt_scr_free(session, &zerobuf); + return (ret); +} + +/* * __log_prealloc -- * Pre-allocate a log file. */ @@ -370,7 +431,15 @@ __log_prealloc(WT_SESSION_IMPL *session, WT_FH *fh) conn = S2C(session); log = conn->log; ret = 0; - if (fh->fallocate_available == WT_FALLOCATE_NOT_AVAILABLE || + /* + * If the user configured zero filling, pre-allocate the log file + * manually. Otherwise use either fallocate or ftruncate to create + * and zero the log file based on what is available. + */ + if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_ZERO_FILL)) + ret = __log_zero(session, fh, + WT_LOG_FIRST_RECORD, conn->log_file_max); + else if (fh->fallocate_available == WT_FALLOCATE_NOT_AVAILABLE || (ret = __wt_fallocate(session, fh, WT_LOG_FIRST_RECORD, conn->log_file_max)) == ENOTSUP) ret = __wt_ftruncate(session, fh, @@ -753,7 +822,7 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created) if (create_log) { log->prep_missed++; WT_RET(__wt_log_allocfile( - session, log->fileid, WT_LOG_FILENAME, true)); + session, log->fileid, WT_LOG_FILENAME)); } WT_RET(__log_openfile(session, false, &log->log_fh, WT_LOG_FILENAME, log->fileid)); @@ -904,7 +973,7 @@ err: WT_TRET(__wt_close(session, &log_fh)); */ int __wt_log_allocfile( - WT_SESSION_IMPL *session, uint32_t lognum, const char *dest, bool prealloc) + WT_SESSION_IMPL *session, uint32_t lognum, const char *dest) { WT_CONNECTION_IMPL *conn; WT_DECL_ITEM(from_path); @@ -936,8 +1005,7 @@ __wt_log_allocfile( WT_ERR(__log_openfile(session, true, &log_fh, WT_LOG_TMPNAME, tmp_id)); WT_ERR(__log_file_header(session, log_fh, NULL, true)); WT_ERR(__wt_ftruncate(session, log_fh, WT_LOG_FIRST_RECORD)); - if (prealloc) - WT_ERR(__log_prealloc(session, log_fh)); + WT_ERR(__log_prealloc(session, log_fh)); WT_ERR(__wt_fsync(session, log_fh)); WT_ERR(__wt_close(session, &log_fh)); WT_ERR(__wt_verbose(session, WT_VERB_LOG, |