From b8d7de319980f9efade92dd0721ed02efcb7e48d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Dec 2010 17:26:00 -0800 Subject: Merge the two conflicting allocation codes into one function, vfs_slow_fallocate() and use that from both the truncate and fill_sparse functions. Jeremy. --- source3/smbd/vfs.c | 79 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 34 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 1829e3ae42..a35142eab1 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -557,6 +557,44 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) return ret; } +/**************************************************************************** + A slow version of posix_fallocate. Fallback code if SMB_VFS_POSIX_FALLOCATE + fails. Needs to be outside of the default version of SMB_VFS_POSIX_FALLOCATE + as this is also called from the default SMB_VFS_FTRUNCATE code. + Returns 0 on success, errno on failure. +****************************************************************************/ + +#define SPARSE_BUF_WRITE_SIZE (32*1024) + +int vfs_slow_fallocate(files_struct *fsp, SMB_OFF_T offset, SMB_OFF_T len) +{ + ssize_t pwrite_ret; + size_t total = 0; + + if (!sparse_buf) { + sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); + if (!sparse_buf) { + errno = ENOMEM; + return ENOMEM; + } + } + + while (total < len) { + size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total)); + + pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total); + if (pwrite_ret == -1) { + DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file " + "%s failed with error %s\n", + fsp_str_dbg(fsp), strerror(errno))); + return errno; + } + total += pwrite_ret; + } + + return 0; +} + /**************************************************************************** A vfs fill sparse call. Writes zeros from the end of file to len, if len is greater than EOF. @@ -564,16 +602,12 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) Returns 0 on success, -1 on failure. ****************************************************************************/ -#define SPARSE_BUF_WRITE_SIZE (32*1024) - int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) { int ret; SMB_STRUCT_STAT st; SMB_OFF_T offset; - size_t total; size_t num_to_write; - ssize_t pwrite_ret; ret = SMB_VFS_FSTAT(fsp, &st); if (ret == -1) { @@ -616,47 +650,24 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) goto out; } if (ret == 0) { - set_filelen_write_cache(fsp, len); goto out; } DEBUG(10,("vfs_fill_sparse: SMB_VFS_POSIX_FALLOCATE failed with " "error %d. Falling back to slow manual allocation\n", ret)); } - if (!sparse_buf) { - sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); - if (!sparse_buf) { - errno = ENOMEM; - ret = -1; - goto out; - } + ret = vfs_slow_fallocate(fsp, offset, num_to_write); + if (ret != 0) { + errno = ret; + ret = -1; } - total = 0; - - while (total < num_to_write) { - size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total)); - - pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total); - if (pwrite_ret == -1) { - DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file " - "%s failed with error %s\n", - fsp_str_dbg(fsp), strerror(errno))); - ret = -1; - goto out; - } - if (pwrite_ret == 0) { - ret = 0; - goto out; - } + out: - total += pwrite_ret; + if (ret == 0) { + set_filelen_write_cache(fsp, len); } - set_filelen_write_cache(fsp, len); - - ret = 0; - out: contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE); return ret; } -- cgit