summaryrefslogtreecommitdiff
path: root/source3/modules/vfs_default.c
diff options
context:
space:
mode:
authorBjörn Jacke <bj@sernet.de>2009-12-02 15:13:37 +0100
committerBjörn Jacke <bj@sernet.de>2009-12-02 21:21:43 +0100
commit95c18626107484d5d1d475e34fc4dde03cfe6ff5 (patch)
tree508651f48665b308ec49ef600f7b58de0916c2a2 /source3/modules/vfs_default.c
parent486c8d57ec5a9aa63aff275621ff45c22b8cde61 (diff)
downloadsamba-95c18626107484d5d1d475e34fc4dde03cfe6ff5.tar.gz
samba-95c18626107484d5d1d475e34fc4dde03cfe6ff5.tar.bz2
samba-95c18626107484d5d1d475e34fc4dde03cfe6ff5.zip
s3: prefer posix_fallocate for doing "strict allocate"
posix_fallocate is more efficient than manual zero'ing the file. When preallocation in kernel space is supported it's extremely fast. Support for preallocation at fs layer via posix_fallocate and fallocate at kernel site can be found in Linux kernel 2.6.23/glibc 2.10 with ext4, XFS and OCFS2. Other systems that I know of which support fast preallocation in kernel space are AIX 6.1 with JFS2 and recent Solaris versions with ZFS maybe UFS2, too. People who have a system with preallocation in kernel space might want to set "strict allocate = yes". This reduces file fragentation and it's also safer for setups with quota being turned on. As of today most systems still don't have preallocation in kernel space, and that's why "strict allocate = no" will stay the default for now.
Diffstat (limited to 'source3/modules/vfs_default.c')
-rw-r--r--source3/modules/vfs_default.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 9abf792769..da775d160b 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -922,8 +922,6 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
if (SMB_VFS_FSTAT(fsp, &st) == -1)
return -1;
- space_to_write = len - st.st_ex_size;
-
#ifdef S_ISFIFO
if (S_ISFIFO(st.st_ex_mode))
return 0;
@@ -936,7 +934,28 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
if (st.st_ex_size > len)
return sys_ftruncate(fsp->fh->fd, len);
+ /* for allocation try posix_fallocate first. This can fail on some
+ platforms e.g. when the filesystem doesn't support it and no
+ emulation is being done by the libc (like on AIX with JFS1). In that
+ case we do our own emulation. posix_fallocate implementations can
+ return ENOTSUP or EINVAL in cases like that. */
+#if defined(HAVE_POSIX_FALLOCATE)
+ {
+ int ret = sys_posix_fallocate(fsp->fh->fd, 0, len);
+ if (ret == ENOSPC) {
+ errno = ENOSPC;
+ return -1;
+ }
+ if (ret == 0) {
+ return 0;
+ }
+ DEBUG(10,("strict_allocate_ftruncate: sys_posix_fallocate "
+ "failed with error %d. "
+ "Falling back to slow manual allocation\n", ret));
+ }
+#endif
/* available disk space is enough or not? */
+ space_to_write = len - st.st_ex_size;
if (lp_strict_allocate(SNUM(fsp->conn))){
uint64_t space_avail;
uint64_t bsize,dfree,dsize;
@@ -956,8 +975,6 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size)
return -1;
- space_to_write = len - st.st_ex_size;
-
memset(zero_space, '\0', sizeof(zero_space));
while ( space_to_write > 0) {
SMB_OFF_T retlen;