summaryrefslogtreecommitdiff
path: root/source3/smbd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/vfs.c')
-rw-r--r--source3/smbd/vfs.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 7042518ce2..8757682242 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -584,6 +584,12 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
return 0;
}
+#ifdef S_ISFIFO
+ if (S_ISFIFO(st.st_ex_mode)) {
+ return 0;
+ }
+#endif
+
DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
"len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
(double)st.st_ex_size, (double)len,
@@ -593,6 +599,30 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
flush_write_cache(fsp, SIZECHANGE_FLUSH);
+ offset = st.st_ex_size;
+ num_to_write = len - st.st_ex_size;
+
+ /* Only do this on non-stream file handles. */
+ if (fsp->base_fsp == NULL) {
+ /* 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. */
+ ret = sys_posix_fallocate(fsp->fh->fd, offset, num_to_write);
+ if (ret == ENOSPC) {
+ errno = ENOSPC;
+ ret = -1;
+ goto out;
+ }
+ if (ret == 0) {
+ set_filelen_write_cache(fsp, len);
+ goto out;
+ }
+ DEBUG(10,("vfs_fill_sparse: sys_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) {
@@ -602,8 +632,6 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
}
}
- offset = st.st_ex_size;
- num_to_write = len - st.st_ex_size;
total = 0;
while (total < num_to_write) {