fix-vfs-prealloc-build   [plain text]


Index: samba/source/configure.in
===================================================================
--- samba/source/configure.in.orig
+++ samba/source/configure.in
@@ -3065,6 +3065,31 @@ exit(1);
   fi
 fi
 
+AC_CACHE_CHECK([for fstore_t], samba_cv_HAVE_FSTORE_T,
+    [
+	AC_TRY_LINK(
+	    [
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+	    ],
+	    [ fstore_t fst; ],
+	    samba_cv_HAVE_FSTORE_T=yes,
+	    samba_cv_HAVE_FSTORE_T=no)
+    ])
+
+if test x"$samba_cv_HAVE_FSTORE_T" = x"yes"; then
+  AC_DEFINE(HAVE_FSTORE_T, 1 ,[Whether fstore_t is available])
+fi
+
 AC_CACHE_CHECK([for st_blocks in struct stat],samba_cv_HAVE_STAT_ST_BLOCKS,[
 AC_TRY_COMPILE([#include <sys/types.h>
 #include <sys/stat.h>
Index: samba/source/modules/vfs_prealloc.c
===================================================================
--- samba/source/modules/vfs_prealloc.c.orig
+++ samba/source/modules/vfs_prealloc.c
@@ -1,7 +1,8 @@
 /*
- * XFS preallocation support module.
+ * File preallocation support module.
  *
  * Copyright (c) James Peach 2006
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,20 +28,35 @@
  * proceed without having to allocate new extents and results in better file
  * layouts on disk.
  *
- * Currently only implemented for XFS. This module is based on an original idea
- * and implementation by Sebastian Brings.
+ * Currently only implemented for XFS ans OS X.
+ *
+ * This module is based on an original idea and implementation by
+ * Sebastian Brings.
  *
  * Tunables.
  *
- *      prealloc: <ext>	    Number of bytes to preallocate for a file with
+ *      prealloc:<ext>	    Number of bytes to preallocate for a file with
  *			    the matching extension.
- *      prealloc:debug	    Debug level at which to emit messages.
+ *      prealloc:msglevel   Debug level at which to emit messages.
  *
  * Example.
  *
- *	prealloc:mpeg = 500M  # Preallocate *.mpeg to 500 MiB.
+ *	prealloc:msglevel = 10	# Emit log/debug messages at level 10
+ *	prealloc:mpeg = 500M	# Preallocate *.mpeg to 500 MiB.
  */
 
+#if defined(F_PREALLOCATE) && defined(HAVE_FSTORE_T)
+#define USE_DARWIN_PREALLOCATE
+#elif defined (HAVE_STRUCT_FLOCK64) || define(HAVE_XFS_LIBXFS_H)
+#define USE_XFS_PREALLOCATE
+#endif
+
+#define MODULE "prealloc"
+static int module_debug;
+
+
+#ifdef USE_XFS_PREALLOCATE
+
 #ifdef HAVE_XFS_LIBXFS_H
 #include <xfs/libxfs.h>
 #define lock_type xfs_flock64_t
@@ -48,39 +64,72 @@
 #define lock_type struct flock64
 #endif
 
-#define MODULE "prealloc"
-static int module_debug;
+static int preallocate_xfs(int fd, lock_type * fl)
+{
+	/* IMPORTANT: We use RESVSP because we want the extents to be
+	 * allocated, but we don't want the allocation to show up in
+	 * st_size or persist after the close(2).
+	 */
+
+#if defined(XFS_IOC_RESVSP64)
+	/* On Linux this comes in via libxfs.h. */
+	return xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl);
+#elif defined(F_RESVSP64)
+	/* On IRIX, this comes from fcntl.h. */
+	return fcntl(fd, F_RESVSP64, &fl);
+#else
+	errno = ENOTSUP;
+	return -1;
+#endif
+
+}
+
+#endif /* USE_XFS_PREALLOCATE */
 
-static int preallocate_space(int fd, SMB_OFF_T size)
+static int preallocate_space(int fd, SMB_OFF_T current, SMB_OFF_T size)
 {
+#if defined(USE_DARWIN_PREALLOCATE)
+	fstore_t fst;
+#elif defined(USE_XFS_PREALLOCATE)
 	lock_type fl = {0};
+#endif
+
 	int err;
 
-	if (size <= 0) {
+	if (size <= 0 || current >= size) {
 		return 0;
 	}
 
+#if defined(USE_DARWIN_PREALLOCATE)
+
+	/* Request best effort for contiguous space. */
+	fst.fst_flags = F_ALLOCATECONTIG;
+
+	/* Add requested allocation to current file size. */
+	fst.fst_posmode = F_PEOFPOSMODE;
+	fst.fst_offset = 0;
+
+	/* Figure out what we need to request since size the the absolute size
+	 * we want.
+	 */
+	fst.fst_length = size - current;
+	fst.fst_bytesalloc = 0;
+
+	err = fcntl(fd, F_PREALLOCATE, &fst);
+
+#elif defined(USE_XFS_PREALLOCATE)
+
 	fl.l_whence = SEEK_SET;
 	fl.l_start = 0;
 	fl.l_len = size;
+	err = preallocate_xfs(fd, &fl);
 
-	/* IMPORTANT: We use RESVSP because we want the extents to be
-	 * allocated, but we don't want the allocation to show up in
-	 * st_size or persist after the close(2).
-	 */
-
-#if defined(XFS_IOC_RESVSP64)
-	/* On Linux this comes in via libxfs.h. */
-	err = xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl);
-#elif defined(F_RESVSP64)
-	/* On IRIX, this comes from fcntl.h. */
-	err = fcntl(fd, F_RESVSP64, &fl);
 #else
 	err = -1;
 	errno = ENOSYS;
 #endif
 
-	if (err) {
+	if (err && errno != ENOTSUP) {
 		DEBUG(module_debug,
 			("%s: preallocate failed on fd=%d size=%lld: %s\n",
 			MODULE, fd, (long long)size, strerror(errno)));
@@ -95,7 +144,7 @@ static int prealloc_connect(
                 const char *                user)
 {
 	    module_debug = lp_parm_int(SNUM(handle->conn),
-					MODULE, "debug", 100);
+					MODULE, "msglevel", 100);
 
 	    return SMB_VFS_NEXT_CONNECT(handle, service, user);
 }
@@ -107,7 +156,7 @@ static int prealloc_open(vfs_handle_stru
 			mode_t		    mode)
 {
 	int fd;
-	off64_t size = 0;
+	SMB_OFF_T size = 0;
 
 	const char * dot;
 	char fext[10];
@@ -167,7 +216,7 @@ static int prealloc_open(vfs_handle_stru
 			MODULE, fname, fd, (long long)size));
 
 		*psize = size;
-		if (preallocate_space(fd, *psize) < 0) {
+		if (preallocate_space(fd, 0, *psize) < 0) {
 			VFS_REMOVE_FSP_EXTENSION(handle, fsp);
 		}
 	}
@@ -191,9 +240,14 @@ static int prealloc_ftruncate(vfs_handle
 	SMB_OFF_T *psize;
 	int ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset);
 
-	/* Maintain the allocated space even in the face of truncates. */
-	if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
-		preallocate_space(fd, *psize);
+	/* Maintain the allocated space even in the face of truncates. If the
+	 * truncate succeeded, we know that the current file size is the size
+	 * the caller requested.
+	 */
+	if (ret == 0 ) {
+		if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+			preallocate_space(fd, offset, *psize);
+		}
 	}
 
 	return ret;
Index: samba/source/lib/util_str.c
===================================================================
--- samba/source/lib/util_str.c.orig
+++ samba/source/lib/util_str.c
@@ -2418,7 +2418,7 @@ SMB_OFF_T conv_str_size(const char * str
 		 * 4-byte SMB_OFF_T. It's better to let the caller handle
 		 * a failure than some random number.
 		 */
-		if (lval_orig <= lval) {
+		if (lval <= lval_orig) {
 			return 0;
 		}
         }