diff options
Diffstat (limited to 'src/os_posix/os_fs.c')
| -rw-r--r-- | src/os_posix/os_fs.c | 616 |
1 files changed, 284 insertions, 332 deletions
diff --git a/src/os_posix/os_fs.c b/src/os_posix/os_fs.c index 86aa8db8f4f..ab9c82613d6 100644 --- a/src/os_posix/os_fs.c +++ b/src/os_posix/os_fs.c @@ -13,30 +13,11 @@ * Underlying support function to flush a file handle. */ static int -__posix_sync(WT_SESSION_IMPL *session, - int fd, const char *name, const char *func, bool block) +__posix_sync( + WT_SESSION_IMPL *session, int fd, const char *name, const char *func) { WT_DECL_RET; - WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_READONLY)); - -#ifdef HAVE_SYNC_FILE_RANGE - if (!block) { - WT_SYSCALL_RETRY(sync_file_range(fd, - (off64_t)0, (off64_t)0, SYNC_FILE_RANGE_WRITE), ret); - if (ret == 0) - return (0); - WT_RET_MSG(session, ret, "%s: %s: sync_file_range", name, func); - } -#else - /* - * Callers attempting asynchronous flush handle ENOTSUP returns, and - * won't make further attempts. - */ - if (!block) - return (ENOTSUP); -#endif - #if defined(F_FULLFSYNC) /* * OS X fsync documentation: @@ -73,45 +54,29 @@ __posix_sync(WT_SESSION_IMPL *session, #endif } +#ifdef __linux__ /* * __posix_directory_sync -- * Flush a directory to ensure file creation is durable. */ static int -__posix_directory_sync(WT_SESSION_IMPL *session, const char *path) +__posix_directory_sync( + WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *path) { -#ifdef __linux__ WT_DECL_RET; + WT_SESSION_IMPL *session; int fd, tret; - const char *dir; - char *copy; - tret = 0; - /* - * POSIX 1003.1 does not require that fsync of a file handle ensures the - * entry in the directory containing the file has also reached disk (and - * there are historic Linux filesystems requiring this), do an explicit - * fsync on a file descriptor for the directory to be sure. - */ - copy = NULL; - if (path == NULL || (dir = strrchr(path, '/')) == NULL) - path = S2C(session)->home; - else { - /* - * Copy the directory name, leaving the trailing slash in place, - * so a path of "/foo" doesn't result in an empty string. - */ - WT_RET(__wt_strndup( - session, path, (size_t)(dir - path) + 1, ©)); - path = copy; - } + WT_UNUSED(file_system); + + session = (WT_SESSION_IMPL *)wt_session; WT_SYSCALL_RETRY(( (fd = open(path, O_RDONLY, 0444)) == -1 ? 1 : 0), ret); if (ret != 0) - WT_ERR_MSG(session, ret, "%s: directory-sync: open", path); + WT_RET_MSG(session, ret, "%s: directory-sync: open", path); - ret = __posix_sync(session, fd, path, "directory-sync", true); + ret = __posix_sync(session, fd, path, "directory-sync"); WT_SYSCALL_RETRY(close(fd), tret); if (tret != 0) { @@ -119,232 +84,182 @@ __posix_directory_sync(WT_SESSION_IMPL *session, const char *path) if (ret == 0) ret = tret; } -err: __wt_free(session, copy); return (ret); -#else - WT_UNUSED(session); - WT_UNUSED(path); - return (0); -#endif } +#endif /* - * __posix_file_exist -- + * __posix_fs_exist -- * Return if the file exists. */ static int -__posix_file_exist(WT_SESSION_IMPL *session, const char *name, bool *existp) +__posix_fs_exist(WT_FILE_SYSTEM *file_system, + WT_SESSION *wt_session, const char *name, bool *existp) { struct stat sb; WT_DECL_RET; - char *path; + WT_SESSION_IMPL *session; - WT_RET(__wt_filename(session, name, &path)); - name = path; + WT_UNUSED(file_system); + + session = (WT_SESSION_IMPL *)wt_session; WT_SYSCALL_RETRY(stat(name, &sb), ret); - if (ret == 0) + if (ret == 0) { *existp = true; - else if (ret == ENOENT) { + return (0); + } + if (ret == ENOENT) { *existp = false; - ret = 0; - } else - __wt_err(session, ret, "%s: file-exist: stat", name); - - __wt_free(session, path); - return (ret); + return (0); + } + WT_RET_MSG(session, ret, "%s: file-exist: stat", name); } /* - * __posix_file_remove -- + * __posix_fs_remove -- * Remove a file. */ static int -__posix_file_remove(WT_SESSION_IMPL *session, const char *name) +__posix_fs_remove( + WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name) { WT_DECL_RET; - char *path; + WT_SESSION_IMPL *session; -#ifdef HAVE_DIAGNOSTIC - if (__wt_handle_search(session, name, false, NULL, NULL)) - WT_RET_MSG(session, EINVAL, - "%s: file-remove: file has open handles", name); -#endif + WT_UNUSED(file_system); - WT_RET(__wt_filename(session, name, &path)); - name = path; + session = (WT_SESSION_IMPL *)wt_session; WT_SYSCALL_RETRY(remove(name), ret); - if (ret != 0) - __wt_err(session, ret, "%s: file-remove: remove", name); - - __wt_free(session, path); - return (ret); + if (ret == 0) + return (0); + WT_RET_MSG(session, ret, "%s: file-remove: remove", name); } /* - * __posix_file_rename -- + * __posix_fs_rename -- * Rename a file. */ static int -__posix_file_rename(WT_SESSION_IMPL *session, const char *from, const char *to) +__posix_fs_rename(WT_FILE_SYSTEM *file_system, + WT_SESSION *wt_session, const char *from, const char *to) { WT_DECL_RET; - char *from_path, *to_path; - -#ifdef HAVE_DIAGNOSTIC - if (__wt_handle_search(session, from, false, NULL, NULL)) - WT_RET_MSG(session, EINVAL, - "%s: file-rename: file has open handles", from); - if (__wt_handle_search(session, to, false, NULL, NULL)) - WT_RET_MSG(session, EINVAL, - "%s: file-rename: file has open handles", to); -#endif + WT_SESSION_IMPL *session; - from_path = to_path = NULL; - WT_ERR(__wt_filename(session, from, &from_path)); - from = from_path; - WT_ERR(__wt_filename(session, to, &to_path)); - to = to_path; + WT_UNUSED(file_system); - WT_SYSCALL_RETRY(rename(from, to), ret); - if (ret != 0) - __wt_err(session, ret, - "%s to %s: file-rename: rename", from, to); + session = (WT_SESSION_IMPL *)wt_session; -err: __wt_free(session, from_path); - __wt_free(session, to_path); - return (ret); + WT_SYSCALL_RETRY(rename(from, to), ret); + if (ret == 0) + return (0); + WT_RET_MSG(session, ret, "%s to %s: file-rename: rename", from, to); } /* - * __posix_file_size -- + * __posix_fs_size -- * Get the size of a file in bytes, by file name. */ static int -__posix_file_size( - WT_SESSION_IMPL *session, const char *name, bool silent, wt_off_t *sizep) +__posix_fs_size(WT_FILE_SYSTEM *file_system, + WT_SESSION *wt_session, const char *name, wt_off_t *sizep) { struct stat sb; WT_DECL_RET; - char *path; + WT_SESSION_IMPL *session; - WT_RET(__wt_filename(session, name, &path)); - name = path; + WT_UNUSED(file_system); + + session = (WT_SESSION_IMPL *)wt_session; - /* - * Optionally don't log errors on ENOENT; some callers of this function - * expect failure in that case and don't want an error message logged. - */ WT_SYSCALL_RETRY(stat(name, &sb), ret); - if (ret == 0) + if (ret == 0) { *sizep = sb.st_size; - else if (ret != ENOENT || !silent) - __wt_err(session, ret, "%s: file-size: stat", name); - - __wt_free(session, path); - - return (ret); + return (0); + } + WT_RET_MSG(session, ret, "%s: file-size: stat", name); } +#if defined(HAVE_POSIX_FADVISE) /* - * __posix_handle_advise -- + * __posix_file_advise -- * POSIX fadvise. */ static int -__posix_handle_advise(WT_SESSION_IMPL *session, - WT_FH *fh, wt_off_t offset, wt_off_t len, int advice) +__posix_file_advise(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, + wt_off_t offset, wt_off_t len, int advice) { -#if defined(HAVE_POSIX_FADVISE) WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; - /* - * Refuse pre-load when direct I/O is configured for the file, the - * kernel cache isn't interesting. - */ - if (advice == POSIX_MADV_WILLNEED && fh->direct_io) - return (ENOTSUP); + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; - WT_SYSCALL_RETRY(posix_fadvise(fh->fd, offset, len, advice), ret); + WT_SYSCALL_RETRY(posix_fadvise(pfh->fd, offset, len, advice), ret); if (ret == 0) return (0); /* * Treat EINVAL as not-supported, some systems don't support some flags. - * Quietly fail, callers expect not-supported failures. + * Quietly fail, callers expect not-supported failures, and reset the + * handle method to prevent future calls. */ - if (ret == EINVAL) + if (ret == EINVAL) { + file_handle->fadvise = NULL; return (ENOTSUP); + } - WT_RET_MSG(session, ret, "%s: handle-advise: posix_fadvise", fh->name); -#else - WT_UNUSED(session); - WT_UNUSED(fh); - WT_UNUSED(offset); - WT_UNUSED(len); - WT_UNUSED(advice); + WT_RET_MSG(session, ret, + "%s: handle-advise: posix_fadvise", file_handle->name); - /* Quietly fail, callers expect not-supported failures. */ - return (ENOTSUP); -#endif } +#endif /* - * __posix_handle_close -- - * ANSI C close/fclose. + * __posix_file_close -- + * ANSI C close. */ static int -__posix_handle_close(WT_SESSION_IMPL *session, WT_FH *fh) +__posix_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session) { WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; - if (fh->fp == NULL) { - WT_SYSCALL_RETRY(close(fh->fd), ret); - if (ret == 0) - return (0); - WT_RET_MSG(session, ret, "%s: handle-close: close", fh->name); - } + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; - /* If the stream was opened for writing, flush the file. */ - if (F_ISSET(fh, WT_FH_FLUSH_ON_CLOSE) && fflush(fh->fp) != 0) { - ret = __wt_errno(); - __wt_err(session, ret, "%s: handle-close: fflush", fh->name); + /* Close the file handle. */ + if (pfh->fd != -1) { + WT_SYSCALL_RETRY(close(pfh->fd), ret); + if (ret != 0) + __wt_err(session, ret, + "%s: handle-close: close", file_handle->name); } - /* Close the file. */ - if (fclose(fh->fp) != 0) { - ret = __wt_errno(); - __wt_err(session, ret, "%s: handle-close: fclose", fh->name); - } + __wt_free(session, file_handle->name); + __wt_free(session, pfh); return (ret); } /* - * __posix_handle_getc -- - * ANSI C fgetc. - */ -static int -__posix_handle_getc(WT_SESSION_IMPL *session, WT_FH *fh, int *chp) -{ - if (fh->fp == NULL) - WT_RET_MSG(session, - ENOTSUP, "%s: handle-getc: no stream configured", fh->name); - - *chp = fgetc(fh->fp); - if (*chp != EOF || !ferror(fh->fp)) - return (0); - WT_RET_MSG(session, __wt_errno(), "%s: handle-getc: fgetc", fh->name); -} - -/* - * __posix_handle_lock -- + * __posix_file_lock -- * Lock/unlock a file. */ static int -__posix_handle_lock(WT_SESSION_IMPL *session, WT_FH *fh, bool lock) +__posix_file_lock( + WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, bool lock) { struct flock fl; WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; + + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; /* * WiredTiger requires this function be able to acquire locks past @@ -360,44 +275,32 @@ __posix_handle_lock(WT_SESSION_IMPL *session, WT_FH *fh, bool lock) fl.l_type = lock ? F_WRLCK : F_UNLCK; fl.l_whence = SEEK_SET; - WT_SYSCALL_RETRY(fcntl(fh->fd, F_SETLK, &fl), ret); + WT_SYSCALL_RETRY(fcntl(pfh->fd, F_SETLK, &fl), ret); if (ret == 0) return (0); - WT_RET_MSG(session, ret, "%s: handle-lock: fcntl", fh->name); + WT_RET_MSG(session, ret, "%s: handle-lock: fcntl", file_handle->name); } /* - * __posix_handle_printf -- - * ANSI C vfprintf. - */ -static int -__posix_handle_printf( - WT_SESSION_IMPL *session, WT_FH *fh, const char *fmt, va_list ap) -{ - if (fh->fp == NULL) - WT_RET_MSG(session, ENOTSUP, - "%s: vfprintf: no stream configured", fh->name); - - if (vfprintf(fh->fp, fmt, ap) >= 0) - return (0); - WT_RET_MSG(session, EIO, "%s: handle-printf: vfprintf", fh->name); -} - -/* - * __posix_handle_read -- + * __posix_file_read -- * POSIX pread. */ static int -__posix_handle_read( - WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, size_t len, void *buf) +__posix_file_read(WT_FILE_HANDLE *file_handle, + WT_SESSION *wt_session, wt_off_t offset, size_t len, void *buf) { + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; size_t chunk; ssize_t nr; uint8_t *addr; + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; + /* Assert direct I/O is aligned and a multiple of the alignment. */ WT_ASSERT(session, - !fh->direct_io || + !pfh->direct_io || S2C(session)->buffer_alignment == 0 || (!((uintptr_t)buf & (uintptr_t)(S2C(session)->buffer_alignment - 1)) && @@ -407,79 +310,122 @@ __posix_handle_read( /* Break reads larger than 1GB into 1GB chunks. */ for (addr = buf; len > 0; addr += nr, len -= (size_t)nr, offset += nr) { chunk = WT_MIN(len, WT_GIGABYTE); - if ((nr = pread(fh->fd, addr, chunk, offset)) <= 0) + if ((nr = pread(pfh->fd, addr, chunk, offset)) <= 0) WT_RET_MSG(session, nr == 0 ? WT_ERROR : __wt_errno(), "%s: handle-read: pread: failed to read %" WT_SIZET_FMT " bytes at offset %" PRIuMAX, - fh->name, chunk, (uintmax_t)offset); + file_handle->name, chunk, (uintmax_t)offset); } return (0); } /* - * __posix_handle_size -- + * __posix_file_size -- * Get the size of a file in bytes, by file handle. */ static int -__posix_handle_size(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t *sizep) +__posix_file_size( + WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t *sizep) { struct stat sb; WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; - WT_SYSCALL_RETRY(fstat(fh->fd, &sb), ret); + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; + + WT_SYSCALL_RETRY(fstat(pfh->fd, &sb), ret); if (ret == 0) { *sizep = sb.st_size; return (0); } - WT_RET_MSG(session, ret, "%s: handle-size: fstat", fh->name); + WT_RET_MSG(session, ret, "%s: handle-size: fstat", file_handle->name); +} + +/* + * __posix_file_sync -- + * POSIX fsync. + */ +static int +__posix_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session) +{ + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; + + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; + + return ( + __posix_sync(session, pfh->fd, file_handle->name, "handle-sync")); } +#ifdef HAVE_SYNC_FILE_RANGE /* - * __posix_handle_sync -- - * POSIX fflush/fsync. + * __posix_file_sync_nowait -- + * POSIX fsync. */ static int -__posix_handle_sync(WT_SESSION_IMPL *session, WT_FH *fh, bool block) +__posix_file_sync_nowait(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session) { - if (fh->fp == NULL) - return (__posix_sync( - session, fh->fd, fh->name, "handle-sync", block)); + WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; + + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; - if (fflush(fh->fp) == 0) + WT_SYSCALL_RETRY(sync_file_range(pfh->fd, + (off64_t)0, (off64_t)0, SYNC_FILE_RANGE_WRITE), ret); + if (ret == 0) return (0); - WT_RET_MSG(session, __wt_errno(), "%s: handle-sync: fflush", fh->name); + WT_RET_MSG(session, ret, + "%s: handle-sync-nowait: sync_file_range", file_handle->name); } +#endif /* - * __posix_handle_truncate -- + * __posix_file_truncate -- * POSIX ftruncate. */ static int -__posix_handle_truncate(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t len) +__posix_file_truncate( + WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t len) { WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; + + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; - WT_SYSCALL_RETRY(ftruncate(fh->fd, len), ret); + WT_SYSCALL_RETRY(ftruncate(pfh->fd, len), ret); if (ret == 0) return (0); - WT_RET_MSG(session, ret, "%s: handle-truncate: ftruncate", fh->name); + WT_RET_MSG(session, ret, + "%s: handle-truncate: ftruncate", file_handle->name); } /* - * __posix_handle_write -- + * __posix_file_write -- * POSIX pwrite. */ static int -__posix_handle_write(WT_SESSION_IMPL *session, - WT_FH *fh, wt_off_t offset, size_t len, const void *buf) +__posix_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, + wt_off_t offset, size_t len, const void *buf) { + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; size_t chunk; ssize_t nw; const uint8_t *addr; + session = (WT_SESSION_IMPL *)wt_session; + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; + /* Assert direct I/O is aligned and a multiple of the alignment. */ WT_ASSERT(session, - !fh->direct_io || + !pfh->direct_io || S2C(session)->buffer_alignment == 0 || (!((uintptr_t)buf & (uintptr_t)(S2C(session)->buffer_alignment - 1)) && @@ -489,21 +435,21 @@ __posix_handle_write(WT_SESSION_IMPL *session, /* Break writes larger than 1GB into 1GB chunks. */ for (addr = buf; len > 0; addr += nw, len -= (size_t)nw, offset += nw) { chunk = WT_MIN(len, WT_GIGABYTE); - if ((nw = pwrite(fh->fd, addr, chunk, offset)) < 0) + if ((nw = pwrite(pfh->fd, addr, chunk, offset)) < 0) WT_RET_MSG(session, __wt_errno(), "%s: handle-write: pwrite: failed to write %" WT_SIZET_FMT " bytes at offset %" PRIuMAX, - fh->name, chunk, (uintmax_t)offset); + file_handle->name, chunk, (uintmax_t)offset); } return (0); } /* - * __posix_handle_open_cloexec -- + * __posix_open_file_cloexec -- * Prevent child access to file handles. */ static inline int -__posix_handle_open_cloexec(WT_SESSION_IMPL *session, int fd, const char *name) +__posix_open_file_cloexec(WT_SESSION_IMPL *session, int fd, const char *name) { #if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) && !defined(O_CLOEXEC) int f; @@ -528,28 +474,35 @@ __posix_handle_open_cloexec(WT_SESSION_IMPL *session, int fd, const char *name) } /* - * __posix_handle_open -- + * __posix_open_file -- * Open a file handle. */ static int -__posix_handle_open(WT_SESSION_IMPL *session, - WT_FH *fh, const char *name, uint32_t file_type, uint32_t flags) +__posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, + const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags, + WT_FILE_HANDLE **file_handlep) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; + WT_FILE_HANDLE *file_handle; + WT_FILE_HANDLE_POSIX *pfh; + WT_SESSION_IMPL *session; mode_t mode; - int f, fd, tret; - bool direct_io; - const char *stream_mode; + int f; + + WT_UNUSED(file_system); + *file_handlep = NULL; + + session = (WT_SESSION_IMPL *)wt_session; conn = S2C(session); - direct_io = false; + + WT_RET(__wt_calloc_one(session, &pfh)); /* Set up error handling. */ - fh->fd = fd = -1; - fh->fp = NULL; + pfh->fd = -1; - if (file_type == WT_FILE_TYPE_DIRECTORY) { + if (file_type == WT_OPEN_FILE_TYPE_DIRECTORY) { f = O_RDONLY; #ifdef O_CLOEXEC /* @@ -560,10 +513,10 @@ __posix_handle_open(WT_SESSION_IMPL *session, f |= O_CLOEXEC; #endif WT_SYSCALL_RETRY(( - (fd = open(name, f, 0444)) == -1 ? 1 : 0), ret); + (pfh->fd = open(name, f, 0444)) == -1 ? 1 : 0), ret); if (ret != 0) WT_ERR_MSG(session, ret, "%s: handle-open: open", name); - WT_ERR(__posix_handle_open_cloexec(session, fd, name)); + WT_ERR(__posix_open_file_cloexec(session, pfh->fd, name)); goto directory_open; } @@ -589,28 +542,20 @@ __posix_handle_open(WT_SESSION_IMPL *session, f |= O_CLOEXEC; #endif #ifdef O_DIRECT - /* - * Direct I/O: file-type is a flag from the set of possible flags stored - * in the connection handle during configuration, check for a match. - * Also, "direct_io=checkpoint" configures direct I/O for readonly data - * files. - */ - if (FLD_ISSET(conn->direct_io, file_type) || - (LF_ISSET(WT_OPEN_READONLY) && - file_type == WT_FILE_TYPE_DATA && - FLD_ISSET(conn->direct_io, WT_FILE_TYPE_CHECKPOINT))) { + /* Direct I/O. */ + if (LF_ISSET(WT_OPEN_DIRECTIO)) { f |= O_DIRECT; - direct_io = true; - } + pfh->direct_io = true; + } else + pfh->direct_io = false; #endif - fh->direct_io = direct_io; #ifdef O_NOATIME /* Avoid updating metadata for read-only workloads. */ - if (file_type == WT_FILE_TYPE_DATA) + if (file_type == WT_OPEN_FILE_TYPE_DATA) f |= O_NOATIME; #endif - if (file_type == WT_FILE_TYPE_LOG && + if (file_type == WT_OPEN_FILE_TYPE_LOG && FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC)) { #ifdef O_DSYNC f |= O_DSYNC; @@ -622,115 +567,122 @@ __posix_handle_open(WT_SESSION_IMPL *session, #endif } - WT_SYSCALL_RETRY(((fd = open(name, f, mode)) == -1 ? 1 : 0), ret); + WT_SYSCALL_RETRY(((pfh->fd = open(name, f, mode)) == -1 ? 1 : 0), ret); if (ret != 0) WT_ERR_MSG(session, ret, - direct_io ? + pfh->direct_io ? "%s: handle-open: open: failed with direct I/O configured, " "some filesystem types do not support direct I/O" : "%s: handle-open: open", name); - WT_ERR(__posix_handle_open_cloexec(session, fd, name)); + WT_ERR(__posix_open_file_cloexec(session, pfh->fd, name)); - /* Disable read-ahead on trees: it slows down random read workloads. */ #if defined(HAVE_POSIX_FADVISE) - if (file_type == WT_FILE_TYPE_DATA) { + /* + * Disable read-ahead on trees: it slows down random read workloads. + * Ignore fadvise when doing direct I/O, the kernel cache isn't + * interesting. + */ + if (!pfh->direct_io && file_type == WT_OPEN_FILE_TYPE_DATA) { WT_SYSCALL_RETRY( - posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM), ret); + posix_fadvise(pfh->fd, 0, 0, POSIX_FADV_RANDOM), ret); if (ret != 0) WT_ERR_MSG(session, ret, "%s: handle-open: posix_fadvise", name); } #endif - /* Optionally configure a stdio stream API. */ - switch (LF_MASK(WT_STREAM_APPEND | WT_STREAM_READ | WT_STREAM_WRITE)) { - case WT_STREAM_APPEND: - stream_mode = "a"; - F_SET(fh, WT_FH_FLUSH_ON_CLOSE); - break; - case WT_STREAM_READ: - stream_mode = "r"; - break; - case WT_STREAM_WRITE: - stream_mode = "w"; - F_SET(fh, WT_FH_FLUSH_ON_CLOSE); - break; - case 0: - default: - stream_mode = NULL; - break; - } - if (stream_mode != NULL) { - if ((fh->fp = fdopen(fd, stream_mode)) == NULL) - WT_ERR_MSG(session, __wt_errno(), - "%s: handle-open: fdopen", name); - if (LF_ISSET(WT_STREAM_LINE_BUFFER)) - __wt_stream_set_line_buffer(fh->fp); - } - directory_open: - fh->fd = fd; - - /* Configure fallocate calls. */ - __wt_posix_handle_allocate_configure(session, fh); - - fh->fh_advise = __posix_handle_advise; - fh->fh_allocate = __wt_posix_handle_allocate; - fh->fh_close = __posix_handle_close; - fh->fh_getc = __posix_handle_getc; - fh->fh_lock = __posix_handle_lock; - fh->fh_map = __wt_posix_map; - fh->fh_map_discard = __wt_posix_map_discard; - fh->fh_map_preload = __wt_posix_map_preload; - fh->fh_map_unmap = __wt_posix_map_unmap; - fh->fh_printf = __posix_handle_printf; - fh->fh_read = __posix_handle_read; - fh->fh_size = __posix_handle_size; - fh->fh_sync = __posix_handle_sync; - fh->fh_truncate = __posix_handle_truncate; - fh->fh_write = __posix_handle_write; + /* Initialize public information. */ + file_handle = (WT_FILE_HANDLE *)pfh; + WT_ERR(__wt_strdup(session, name, &file_handle->name)); + + file_handle->close = __posix_file_close; +#if defined(HAVE_POSIX_FADVISE) + /* + * Ignore fadvise when doing direct I/O, the kernel cache isn't + * interesting. + */ + if (!pfh->direct_io) + file_handle->fadvise = __posix_file_advise; +#endif + file_handle->fallocate = __wt_posix_file_fallocate; + file_handle->lock = __posix_file_lock; +#ifdef WORDS_BIGENDIAN + /* + * The underlying objects are little-endian, mapping objects isn't + * currently supported on big-endian systems. + */ +#else + file_handle->map = __wt_posix_map; +#ifdef HAVE_POSIX_MADVISE + file_handle->map_discard = __wt_posix_map_discard; + file_handle->map_preload = __wt_posix_map_preload; +#endif + file_handle->unmap = __wt_posix_unmap; +#endif + file_handle->read = __posix_file_read; + file_handle->size = __posix_file_size; + file_handle->sync = __posix_file_sync; +#ifdef HAVE_SYNC_FILE_RANGE + file_handle->sync_nowait = __posix_file_sync_nowait; +#endif + file_handle->truncate = __posix_file_truncate; + file_handle->write = __posix_file_write; + + *file_handlep = file_handle; return (0); -err: if (fd != -1) { - WT_SYSCALL_RETRY(close(fd), tret); - if (tret != 0) - __wt_err(session, tret, "%s: handle-open: close", name); - } +err: WT_TRET(__posix_file_close((WT_FILE_HANDLE *)pfh, wt_session)); return (ret); } /* - * __wt_os_posix -- - * Initialize a POSIX configuration. + * __posix_terminate -- + * Terminate a POSIX configuration. */ -int -__wt_os_posix(WT_SESSION_IMPL *session) +static int +__posix_terminate(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session) { - WT_CONNECTION_IMPL *conn; + WT_SESSION_IMPL *session; - conn = S2C(session); + WT_UNUSED(file_system); - /* Initialize the POSIX jump table. */ - conn->file_directory_list = __wt_posix_directory_list; - conn->file_directory_sync = __posix_directory_sync; - conn->file_exist = __posix_file_exist; - conn->file_remove = __posix_file_remove; - conn->file_rename = __posix_file_rename; - conn->file_size = __posix_file_size; - conn->handle_open = __posix_handle_open; + session = (WT_SESSION_IMPL *)wt_session; + __wt_free(session, file_system); return (0); } /* - * __wt_os_posix_cleanup -- - * Discard a POSIX configuration. + * __wt_os_posix -- + * Initialize a POSIX configuration. */ int -__wt_os_posix_cleanup(WT_SESSION_IMPL *session) +__wt_os_posix(WT_SESSION_IMPL *session) { - WT_UNUSED(session); + WT_CONNECTION_IMPL *conn; + WT_FILE_SYSTEM *file_system; + + conn = S2C(session); + + WT_RET(__wt_calloc_one(session, &file_system)); + + /* Initialize the POSIX jump table. */ + file_system->directory_list = __wt_posix_directory_list; + file_system->directory_list_free = __wt_posix_directory_list_free; +#ifdef __linux__ + file_system->directory_sync = __posix_directory_sync; +#endif + file_system->exist = __posix_fs_exist; + file_system->open_file = __posix_open_file; + file_system->remove = __posix_fs_remove; + file_system->rename = __posix_fs_rename; + file_system->size = __posix_fs_size; + file_system->terminate = __posix_terminate; + + /* Switch it into place. */ + conn->file_system = file_system; return (0); } |
