The branch, v3-6-test has been updated via a88b89d Move posix_fallocate into the VFS where it belongs. via 6fb840d Fix bug #7835 - vfs_fill_sparse() doesn't use posix_fallocate when strict allocate is on from 6b836d7 s3-waf: more krb5 configure checks.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test - Log ----------------------------------------------------------------- commit a88b89dfc18b3cf4ab01441dfb0a12b33157eb6d Author: Jeremy Allison <j...@samba.org> Date: Thu Dec 2 16:25:59 2010 -0800 Move posix_fallocate into the VFS where it belongs. Jeremy. (cherry picked from commit 5819a36aef030772f1e9da81655c1f911a10372c) commit 6fb840ddeec3c5edd7060a6a96de6780c524a90d Author: Jeremy Allison <j...@samba.org> Date: Thu Dec 2 15:38:36 2010 -0800 Fix bug #7835 - vfs_fill_sparse() doesn't use posix_fallocate when strict allocate is on Tries posix_fallocate() and then falls back to old code. Jeremy. (cherry picked from commit de8ceb5364de86f9b016251201474f011c16f6cb) ----------------------------------------------------------------------- Summary of changes: examples/VFS/skel_opaque.c | 8 ++++++ examples/VFS/skel_transparent.c | 8 ++++++ source3/include/smbprofile.h | 4 +++ source3/include/vfs.h | 10 ++++++++ source3/include/vfs_macros.h | 5 ++++ source3/modules/vfs_default.c | 17 ++++++++++++- source3/modules/vfs_full_audit.c | 17 ++++++++++++++ source3/modules/vfs_streams_xattr.c | 26 ++++++++++++++++++++++ source3/modules/vfs_time_audit.c | 22 ++++++++++++++++++ source3/profile/profile.c | 1 + source3/smbd/vfs.c | 41 +++++++++++++++++++++++++++++++++- 11 files changed, 155 insertions(+), 4 deletions(-) Changeset truncated at 500 lines: diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 42f4e48..40ee5e9 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -308,6 +308,13 @@ static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_ return -1; } +static int skel_posix_fallocate(vfs_handle_struct *handle, files_struct *fsp, + SMB_OFF_T offset, SMB_OFF_T len) +{ + errno = ENOSYS; + return -1; +} + static bool skel_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { errno = ENOSYS; @@ -813,6 +820,7 @@ struct vfs_fn_pointers skel_transparent_fns = { .getwd = skel_getwd, .ntimes = skel_ntimes, .ftruncate = skel_ftruncate, + .posix_fallocate = skel_posix_fallocate, .lock = skel_lock, .kernel_flock = skel_kernel_flock, .linux_setlease = skel_linux_setlease, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 42e54a8..ca22a30 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -292,6 +292,13 @@ static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_ return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); } +static int skel_posix_fallocate(vfs_handle_struct *handle, files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len) +{ + return SMB_VFS_NEXT_POSIX_FALLOCATE(handle, fsp, offset, len); +} + static bool skel_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { return SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type); @@ -757,6 +764,7 @@ struct vfs_fn_pointers skel_transparent_fns = { .getwd = skel_getwd, .ntimes = skel_ntimes, .ftruncate = skel_ftruncate, + .posix_fallocate = skel_posix_fallocate, .lock = skel_lock, .kernel_flock = skel_kernel_flock, .linux_setlease = skel_linux_setlease, diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index 5015d2a..647bf17 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -179,6 +179,10 @@ enum profile_stats_values #define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count) #define syscall_ftruncate_time __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, time) + PR_VALUE_SYSCALL_POSIX_FALLOCATE, +#define syscall_posix_fallocate_count __profile_stats_value(PR_VALUE_SYSCALL_POSIX_FALLOCATE, count) +#define syscall_posix_fallocate_time __profile_stats_value(PR_VALUE_SYSCALL_POSIX_FALLOCATE, time) + PR_VALUE_SYSCALL_FCNTL_LOCK, #define syscall_fcntl_lock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, count) #define syscall_fcntl_lock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, time) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 9121069..cb49a17 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -128,6 +128,8 @@ /* Changed to version 28 - Add private_flags uint32_t to CREATE call. */ /* Leave at 28 - not yet released. Change realpath to assume NULL and return a malloc'ed path. JRA. */ +/* Leave at 28 - not yet released. Move posix_fallocate into the VFS + where it belongs. JRA. */ #define SMB_VFS_INTERFACE_VERSION 28 @@ -250,6 +252,10 @@ struct vfs_fn_pointers { const struct smb_filename *smb_fname, struct smb_file_time *ft); int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_OFF_T offset); + int (*posix_fallocate)(struct vfs_handle_struct *handle, + struct files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len); bool (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 share_mode, uint32_t access_mask); @@ -602,6 +608,10 @@ int smb_vfs_call_ntimes(struct vfs_handle_struct *handle, struct smb_file_time *ft); int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_OFF_T offset); +int smb_vfs_call_posix_fallocate(struct vfs_handle_struct *handle, + struct files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len); bool smb_vfs_call_lock(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 5b38e64..2eedd2b 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -249,6 +249,11 @@ #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset) \ smb_vfs_call_ftruncate((handle)->next, (fsp), (offset)) +#define SMB_VFS_POSIX_FALLOCATE(fsp, offset, len) \ + smb_vfs_call_posix_fallocate((fsp)->conn->vfs_handles, (fsp), (offset), (len)) +#define SMB_VFS_NEXT_POSIX_FALLOCATE(handle, fsp, offset, len) \ + smb_vfs_call_posix_fallocate((handle)->next, (fsp), (offset), (len)) + #define SMB_VFS_LOCK(fsp, op, offset, count, type) \ smb_vfs_call_lock((fsp)->conn->vfs_handles, (fsp), (op), (offset), (count), (type)) #define SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type) \ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 977a563..63993fe 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -854,7 +854,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs 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, st.st_ex_size, space_to_write); + ret = SMB_VFS_POSIX_FALLOCATE(fsp, st.st_ex_size, space_to_write); if (ret == ENOSPC) { errno = ENOSPC; return -1; @@ -862,7 +862,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs if (ret == 0) { return 0; } - DEBUG(10,("strict_allocate_ftruncate: sys_posix_fallocate failed with " + DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_POSIX_FALLOCATE failed with " "error %d. Falling back to slow manual allocation\n", ret)); /* available disk space is enough or not? */ @@ -974,6 +974,19 @@ static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_O return result; } +static int vfswrap_posix_fallocate(vfs_handle_struct *handle, + files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len) +{ + int result; + + START_PROFILE(syscall_posix_fallocate); + result = sys_posix_fallocate(fsp->fh->fd, offset, len); + END_PROFILE(syscall_posix_fallocate); + return result; +} + static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { bool result; diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 3328128..b7c0888 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -124,6 +124,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_GETWD, SMB_VFS_OP_NTIMES, SMB_VFS_OP_FTRUNCATE, + SMB_VFS_OP_POSIX_FALLOCATE, SMB_VFS_OP_LOCK, SMB_VFS_OP_KERNEL_FLOCK, SMB_VFS_OP_LINUX_SETLEASE, @@ -262,6 +263,7 @@ static struct { { SMB_VFS_OP_GETWD, "getwd" }, { SMB_VFS_OP_NTIMES, "ntimes" }, { SMB_VFS_OP_FTRUNCATE, "ftruncate" }, + { SMB_VFS_OP_POSIX_FALLOCATE,"posix_fallocate" }, { SMB_VFS_OP_LOCK, "lock" }, { SMB_VFS_OP_KERNEL_FLOCK, "kernel_flock" }, { SMB_VFS_OP_LINUX_SETLEASE, "linux_setlease" }, @@ -1222,6 +1224,20 @@ static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp return result; } +static int smb_full_audit_posix_fallocate(vfs_handle_struct *handle, files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len) +{ + int result; + + result = SMB_VFS_NEXT_POSIX_FALLOCATE(handle, fsp, offset, len); + + do_log(SMB_VFS_OP_POSIX_FALLOCATE, (result >= 0), handle, + "%s", fsp_str_do_log(fsp)); + + return result; +} + static bool smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { @@ -2218,6 +2234,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = { .getwd = smb_full_audit_getwd, .ntimes = smb_full_audit_ntimes, .ftruncate = smb_full_audit_ftruncate, + .posix_fallocate = smb_full_audit_posix_fallocate, .lock = smb_full_audit_lock, .kernel_flock = smb_full_audit_kernel_flock, .linux_setlease = smb_full_audit_linux_setlease, diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 218e5ec..8870c6e 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -1023,6 +1023,31 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, return 0; } +static int streams_xattr_posix_fallocate(struct vfs_handle_struct *handle, + struct files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len) +{ + struct stream_io *sio = + (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); + + DEBUG(10, ("streams_xattr_posix_fallocate called for file %s offset %.0f" + "len = %.0f\n", + fsp_str_dbg(fsp), (double)offset, (double)len)); + + if (sio == NULL) { + return SMB_VFS_NEXT_POSIX_FALLOCATE(handle, fsp, offset, len); + } + + if (!streams_xattr_recheck(sio)) { + return -1; + } + + /* Let the pwrite code path handle it. */ + return ENOSYS; +} + + static struct vfs_fn_pointers vfs_streams_xattr_fns = { .fs_capabilities = streams_xattr_fs_capabilities, .open = streams_xattr_open, @@ -1034,6 +1059,7 @@ static struct vfs_fn_pointers vfs_streams_xattr_fns = { .unlink = streams_xattr_unlink, .rename = streams_xattr_rename, .ftruncate = streams_xattr_ftruncate, + .posix_fallocate = streams_xattr_posix_fallocate, .streaminfo = streams_xattr_streaminfo, }; diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index af4fd33..e9481b5 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -905,6 +905,27 @@ static int smb_time_audit_ftruncate(vfs_handle_struct *handle, return result; } +static int smb_time_audit_posix_fallocate(vfs_handle_struct *handle, + files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len) +{ + int result; + struct timespec ts1,ts2; + double timediff; + + clock_gettime_mono(&ts1); + result = SMB_VFS_NEXT_POSIX_FALLOCATE(handle, fsp, offset, len); + clock_gettime_mono(&ts2); + timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; + + if (timediff > audit_timeout) { + smb_time_audit_log("posix_fallocate", timediff); + } + + return result; +} + static bool smb_time_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) @@ -2336,6 +2357,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = { .getwd = smb_time_audit_getwd, .ntimes = smb_time_audit_ntimes, .ftruncate = smb_time_audit_ftruncate, + .posix_fallocate = smb_time_audit_posix_fallocate, .lock = smb_time_audit_lock, .kernel_flock = smb_time_audit_kernel_flock, .linux_setlease = smb_time_audit_linux_setlease, diff --git a/source3/profile/profile.c b/source3/profile/profile.c index 59b409d..8013fc3 100644 --- a/source3/profile/profile.c +++ b/source3/profile/profile.c @@ -234,6 +234,7 @@ bool profile_setup(struct messaging_context *msg_ctx, bool rdonly) "syscall_getwd", /* PR_VALUE_SYSCALL_GETWD */ "syscall_ntimes", /* PR_VALUE_SYSCALL_NTIMES */ "syscall_ftruncate", /* PR_VALUE_SYSCALL_FTRUNCATE */ + "syscall_posix_fallocate", /* PR_VALUE_SYSCALL_POSIX_FALLOCATE */ "syscall_fcntl_lock", /* PR_VALUE_SYSCALL_FCNTL_LOCK */ "syscall_kernel_flock", /* PR_VALUE_SYSCALL_KERNEL_FLOCK */ "syscall_linux_setlease", /* PR_VALUE_SYSCALL_LINUX_SETLEASE */ diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7042518..1829e3a 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 = SMB_VFS_POSIX_FALLOCATE(fsp, 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: 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) { @@ -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) { @@ -1411,6 +1439,15 @@ int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle, return handle->fns->ftruncate(handle, fsp, offset); } +int smb_vfs_call_posix_fallocate(struct vfs_handle_struct *handle, + struct files_struct *fsp, + SMB_OFF_T offset, + SMB_OFF_T len) +{ + VFS_FIND(posix_fallocate); + return handle->fns->posix_fallocate(handle, fsp, offset, len); +} + int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 share_mode, uint32_t access_mask) -- Samba Shared Repository