diff options
Diffstat (limited to 'src/os_posix/os_fallocate.c')
-rw-r--r-- | src/os_posix/os_fallocate.c | 160 |
1 files changed, 70 insertions, 90 deletions
diff --git a/src/os_posix/os_fallocate.c b/src/os_posix/os_fallocate.c index 22879d36182..a162dbe01a1 100644 --- a/src/os_posix/os_fallocate.c +++ b/src/os_posix/os_fallocate.c @@ -12,47 +12,28 @@ #include <linux/falloc.h> #include <sys/syscall.h> #endif -/* - * __wt_posix_handle_allocate_configure -- - * Configure POSIX file-extension behavior for a file handle. - */ -void -__wt_posix_handle_allocate_configure(WT_SESSION_IMPL *session, WT_FH *fh) -{ - WT_UNUSED(session); - - fh->fallocate_available = WT_FALLOCATE_NOT_AVAILABLE; - fh->fallocate_requires_locking = false; - - /* - * Check for the availability of some form of fallocate; in all cases, - * start off requiring locking, we'll relax that requirement once we - * know which system calls work with the handle's underlying filesystem. - */ -#if defined(HAVE_FALLOCATE) || defined(HAVE_POSIX_FALLOCATE) - fh->fallocate_available = WT_FALLOCATE_AVAILABLE; - fh->fallocate_requires_locking = true; -#endif -#if defined(__linux__) && defined(SYS_fallocate) - fh->fallocate_available = WT_FALLOCATE_AVAILABLE; - fh->fallocate_requires_locking = true; -#endif -} /* * __posix_std_fallocate -- * Linux fallocate call. */ static int -__posix_std_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) +__posix_std_fallocate(WT_FILE_HANDLE *file_handle, + WT_SESSION *wt_session, wt_off_t offset, wt_off_t len) { #if defined(HAVE_FALLOCATE) WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; - WT_SYSCALL_RETRY(fallocate(fh->fd, 0, offset, len), ret); + WT_UNUSED(wt_session); + + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; + + WT_SYSCALL_RETRY(fallocate(pfh->fd, 0, offset, len), ret); return (ret); #else - WT_UNUSED(fh); + WT_UNUSED(file_handle); + WT_UNUSED(wt_session); WT_UNUSED(offset); WT_UNUSED(len); return (ENOTSUP); @@ -64,10 +45,16 @@ __posix_std_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) * Linux fallocate call (system call version). */ static int -__posix_sys_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) +__posix_sys_fallocate(WT_FILE_HANDLE *file_handle, + WT_SESSION *wt_session, wt_off_t offset, wt_off_t len) { #if defined(__linux__) && defined(SYS_fallocate) WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + + WT_UNUSED(wt_session); + + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; /* * Try the system call for fallocate even if the C library wrapper was @@ -75,10 +62,11 @@ __posix_sys_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) * Linux versions (RHEL 5.5), but not in the version of the C library. * This allows it to work everywhere the kernel supports it. */ - WT_SYSCALL_RETRY(syscall(SYS_fallocate, fh->fd, 0, offset, len), ret); + WT_SYSCALL_RETRY(syscall(SYS_fallocate, pfh->fd, 0, offset, len), ret); return (ret); #else - WT_UNUSED(fh); + WT_UNUSED(file_handle); + WT_UNUSED(wt_session); WT_UNUSED(offset); WT_UNUSED(len); return (ENOTSUP); @@ -90,15 +78,22 @@ __posix_sys_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) * POSIX fallocate call. */ static int -__posix_posix_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) +__posix_posix_fallocate(WT_FILE_HANDLE *file_handle, + WT_SESSION *wt_session, wt_off_t offset, wt_off_t len) { #if defined(HAVE_POSIX_FALLOCATE) WT_DECL_RET; + WT_FILE_HANDLE_POSIX *pfh; + + WT_UNUSED(wt_session); - WT_SYSCALL_RETRY(posix_fallocate(fh->fd, offset, len), ret); + pfh = (WT_FILE_HANDLE_POSIX *)file_handle; + + WT_SYSCALL_RETRY(posix_fallocate(pfh->fd, offset, len), ret); return (ret); #else - WT_UNUSED(fh); + WT_UNUSED(file_handle); + WT_UNUSED(wt_session); WT_UNUSED(offset); WT_UNUSED(len); return (ENOTSUP); @@ -106,67 +101,52 @@ __posix_posix_fallocate(WT_FH *fh, wt_off_t offset, wt_off_t len) } /* - * __wt_posix_handle_allocate -- + * __wt_posix_file_fallocate -- * POSIX fallocate. */ int -__wt_posix_handle_allocate( - WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, wt_off_t len) +__wt_posix_file_fallocate(WT_FILE_HANDLE *file_handle, + WT_SESSION *wt_session, wt_off_t offset, wt_off_t len) { - WT_DECL_RET; - - switch (fh->fallocate_available) { - /* - * Check for already configured handles and make the configured call. - */ - case WT_FALLOCATE_POSIX: - if ((ret = __posix_posix_fallocate(fh, offset, len)) == 0) - return (0); - WT_RET_MSG(session, ret, "%s: posix_fallocate", fh->name); - case WT_FALLOCATE_STD: - if ((ret = __posix_std_fallocate(fh, offset, len)) == 0) - return (0); - WT_RET_MSG(session, ret, "%s: fallocate", fh->name); - case WT_FALLOCATE_SYS: - if ((ret = __posix_sys_fallocate(fh, offset, len)) == 0) - return (0); - WT_RET_MSG(session, ret, "%s: sys_fallocate", fh->name); - /* - * Figure out what allocation call this system/filesystem supports, if - * any. + * The first fallocate call: figure out what fallocate call this system + * supports, if any. + * + * The function is configured as a locking fallocate call, so we know + * we're single-threaded through here. Set the nolock function first, + * then publish the NULL replacement to ensure the handle functions are + * always correct. + * + * We've seen Linux systems where posix_fallocate has corrupted + * existing file data (even though that is explicitly disallowed + * by POSIX). FreeBSD and Solaris support posix_fallocate, and + * so far we've seen no problems leaving it unlocked. Check for + * fallocate (and the system call version of fallocate) first to + * avoid locking on Linux if at all possible. */ - case WT_FALLOCATE_AVAILABLE: - /* - * We've seen Linux systems where posix_fallocate has corrupted - * existing file data (even though that is explicitly disallowed - * by POSIX). FreeBSD and Solaris support posix_fallocate, and - * so far we've seen no problems leaving it unlocked. Check for - * fallocate (and the system call version of fallocate) first to - * avoid locking on Linux if at all possible. - */ - if ((ret = __posix_std_fallocate(fh, offset, len)) == 0) { - fh->fallocate_available = WT_FALLOCATE_STD; - fh->fallocate_requires_locking = false; - return (0); - } - if ((ret = __posix_sys_fallocate(fh, offset, len)) == 0) { - fh->fallocate_available = WT_FALLOCATE_SYS; - fh->fallocate_requires_locking = false; - return (0); - } - if ((ret = __posix_posix_fallocate(fh, offset, len)) == 0) { - fh->fallocate_available = WT_FALLOCATE_POSIX; -#if !defined(__linux__) - fh->fallocate_requires_locking = false; + if (__posix_std_fallocate(file_handle, wt_session, offset, len) == 0) { + file_handle->fallocate_nolock = __posix_std_fallocate; + WT_PUBLISH(file_handle->fallocate, NULL); + return (0); + } + if (__posix_sys_fallocate(file_handle, wt_session, offset, len) == 0) { + file_handle->fallocate_nolock = __posix_sys_fallocate; + WT_PUBLISH(file_handle->fallocate, NULL); + return (0); + } + if (__posix_posix_fallocate( + file_handle, wt_session, offset, len) == 0) { +#if defined(__linux__) + file_handle->fallocate = __posix_posix_fallocate; + WT_WRITE_BARRIER(); +#else + file_handle->fallocate_nolock = __posix_posix_fallocate; + WT_PUBLISH(file_handle->fallocate, NULL); #endif - return (0); - } - /* FALLTHROUGH */ - case WT_FALLOCATE_NOT_AVAILABLE: - default: - fh->fallocate_available = WT_FALLOCATE_NOT_AVAILABLE; - return (ENOTSUP); + return (0); } - /* NOTREACHED */ + + file_handle->fallocate = NULL; + WT_WRITE_BARRIER(); + return (ENOTSUP); } |