1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

Merge the two conflicting allocation codes into one function, vfs_slow_fallocate()

and use that from both the truncate and fill_sparse functions.

Jeremy.
This commit is contained in:
Jeremy Allison 2010-12-02 17:26:00 -08:00
parent 1f1491da5a
commit b8d7de3199
3 changed files with 52 additions and 58 deletions

View File

@ -5562,6 +5562,7 @@ ssize_t vfs_pwrite_data(struct smb_request *req,
SMB_OFF_T offset);
int vfs_allocate_file_space(files_struct *fsp, uint64_t len);
int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len);
int vfs_slow_fallocate(files_struct *fsp, SMB_OFF_T offset, SMB_OFF_T len);
int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len);
SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n);
const char *vfs_readdirname(connection_struct *conn, void *p,

View File

@ -822,16 +822,11 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
{
SMB_STRUCT_STAT st;
SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
unsigned char zero_space[4096];
SMB_OFF_T space_to_write;
uint64_t space_avail;
uint64_t bsize,dfree,dsize;
int ret;
if (currpos == -1)
return -1;
if (SMB_VFS_FSTAT(fsp, &st) == -1)
return -1;
@ -877,25 +872,12 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
}
/* Write out the real space on disk. */
if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size)
return -1;
memset(zero_space, '\0', sizeof(zero_space));
while ( space_to_write > 0) {
SMB_OFF_T retlen;
SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
retlen = SMB_VFS_WRITE(fsp,(char *)zero_space,current_len_to_write);
if (retlen <= 0)
return -1;
space_to_write -= retlen;
ret = vfs_slow_fallocate(fsp, st.st_ex_size, space_to_write);
if (ret != 0) {
errno = ret;
ret = -1;
}
/* Seek to where we were */
if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
return -1;
return 0;
}

View File

@ -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;
}
total += pwrite_ret;
}
set_filelen_write_cache(fsp, len);
ret = 0;
out:
if (ret == 0) {
set_filelen_write_cache(fsp, len);
}
contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
return ret;
}