Index: samba/source/configure.in =================================================================== --- samba/source/configure.in.orig +++ samba/source/configure.in @@ -3084,6 +3084,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 +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_SYS_FCNTL_H +#include +#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 #include 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: Number of bytes to preallocate for a file with + * prealloc: 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 #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 @@ -2432,7 +2432,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; } }