summaryrefslogtreecommitdiff
path: root/src/os_posix/os_fallocate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_posix/os_fallocate.c')
-rw-r--r--src/os_posix/os_fallocate.c160
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);
}