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:
parent
1f1491da5a
commit
b8d7de3199
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user