From 6740293969ba4b5bc14f33f30601710e192090f7 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Tue, 26 Feb 2019 21:26:27 +0100 Subject: [PATCH 1/3] vfs_ceph: add missing fallocate hook SMB_VFS_FALLOCATE() calls atop a vfs_ceph share currently fall through to vfs_default, which results in a local filesystem I/O attempt using a libcephfs file-descriptor. Add the missing fallocate hook to vfs_ceph. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13807 Signed-off-by: David Disseldorp Reviewed-by: Guenther Deschner (cherry picked from commit 5a7e7280813559fb70a9fc8e4238cb6015ee3b53) --- source3/modules/vfs_ceph.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 47371bc9e08..9f111bea2a0 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -1155,6 +1155,22 @@ static int cephwrap_ftruncate(struct vfs_handle_struct *handle, files_struct *fs return result; } +static int cephwrap_fallocate(struct vfs_handle_struct *handle, + struct files_struct *fsp, + uint32_t mode, + off_t offset, + off_t len) +{ + int result; + + DBG_DEBUG("[CEPH] fallocate(%p, %p, %u, %llu, %llu\n", + handle, fsp, mode, llu(offset), llu(len)); + /* unsupported mode flags are rejected by libcephfs */ + result = ceph_fallocate(handle->data, fsp->fh->fd, mode, offset, len); + DBG_DEBUG("[CEPH] fallocate(...) = %d\n", result); + WRAP_RETURN(result); +} + static bool cephwrap_lock(struct vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type) { DBG_DEBUG("[CEPH] lock\n"); @@ -1513,6 +1529,7 @@ static struct vfs_fn_pointers ceph_fns = { .getwd_fn = cephwrap_getwd, .ntimes_fn = cephwrap_ntimes, .ftruncate_fn = cephwrap_ftruncate, + .fallocate_fn = cephwrap_fallocate, .lock_fn = cephwrap_lock, .kernel_flock_fn = cephwrap_kernel_flock, .linux_setlease_fn = cephwrap_linux_setlease, -- 2.13.7 From 586896bae99213ae2b5ab14b37ea96a77ceb9061 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Tue, 26 Feb 2019 16:07:27 +0100 Subject: [PATCH 2/3] vfs_ceph: fix strict_allocate_ftruncate() The vfs_ceph "strict allocate = yes" ftruncate wrapper may attempt *local* filesystem ftruncate(). Fix this. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13807 Signed-off-by: David Disseldorp Reviewed-by: Guenther Deschner (cherry picked from commit 70329c36ed91dd0e50ff66f9b0a85c62ac8a621e) --- source3/modules/vfs_ceph.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 9f111bea2a0..4a705ea14a3 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -1053,8 +1053,10 @@ static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_str return 0; /* Shrink - just ftruncate. */ - if (pst->st_ex_size > len) - return ftruncate(fsp->fh->fd, len); + if (pst->st_ex_size > len) { + ret = ceph_ftruncate(handle->data, fsp->fh->fd, len); + WRAP_RETURN(ret); + } space_to_write = len - pst->st_ex_size; -- 2.13.7 From 376a509eaf72910edcb8a6476b8fe00a81ede44a Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 27 Feb 2019 11:52:42 +0100 Subject: [PATCH 3/3] vfs_ceph: remove ceph_fallocate/ceph_ftruncate fallback Both libcephfs functions are supported and capable of extending files, so fallback can be dropped. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13807 Signed-off-by: David Disseldorp Reviewed-by: Guenther Deschner (cherry picked from commit 155f1289ba7a4802fbb99fbc9ea90d8bc6cff0c9) --- source3/modules/vfs_ceph.c | 97 ++++------------------------------------------ 1 file changed, 8 insertions(+), 89 deletions(-) diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 4a705ea14a3..a3fd6095ef5 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -1032,9 +1032,7 @@ static struct smb_filename *cephwrap_getwd(struct vfs_handle_struct *handle, static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len) { off_t space_to_write; - uint64_t space_avail; - uint64_t bsize,dfree,dsize; - int ret; + int result; NTSTATUS status; SMB_STRUCT_STAT *pst; @@ -1054,107 +1052,28 @@ static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_str /* Shrink - just ftruncate. */ if (pst->st_ex_size > len) { - ret = ceph_ftruncate(handle->data, fsp->fh->fd, len); - WRAP_RETURN(ret); + result = ceph_ftruncate(handle->data, fsp->fh->fd, len); + WRAP_RETURN(result); } space_to_write = len - pst->st_ex_size; - - /* for allocation try 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. fallocate implementations can - return ENOTSUP or EINVAL in cases like that. */ - ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write); - if (ret == -1 && errno == ENOSPC) { - return -1; - } - if (ret == 0) { - return 0; - } - DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with " - "error %d. Falling back to slow manual allocation\n", errno)); - - /* available disk space is enough or not? */ - space_avail = - get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize); - /* space_avail is 1k blocks */ - if (space_avail == (uint64_t)-1 || - ((uint64_t)space_to_write/1024 > space_avail) ) { - errno = ENOSPC; - return -1; - } - - /* Write out the real space on disk. */ - return vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write); + result = ceph_fallocate(handle->data, fsp->fh->fd, 0, pst->st_ex_size, + space_to_write); + WRAP_RETURN(result); } static int cephwrap_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len) { int result = -1; - SMB_STRUCT_STAT st; - char c = 0; - off_t currpos; DBG_DEBUG("[CEPH] ftruncate(%p, %p, %llu\n", handle, fsp, llu(len)); if (lp_strict_allocate(SNUM(fsp->conn))) { - result = strict_allocate_ftruncate(handle, fsp, len); - return result; + return strict_allocate_ftruncate(handle, fsp, len); } - /* we used to just check HAVE_FTRUNCATE_EXTEND and only use - sys_ftruncate if the system supports it. Then I discovered that - you can have some filesystems that support ftruncate - expansion and some that don't! On Linux fat can't do - ftruncate extend but ext2 can. */ - result = ceph_ftruncate(handle->data, fsp->fh->fd, len); - if (result == 0) - goto done; - - /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot - extend a file with ftruncate. Provide alternate implementation - for this */ - currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR); - if (currpos == -1) { - goto done; - } - - /* Do an fstat to see if the file is longer than the requested - size in which case the ftruncate above should have - succeeded or shorter, in which case seek to len - 1 and - write 1 byte of zero */ - if (SMB_VFS_FSTAT(fsp, &st) == -1) { - goto done; - } - -#ifdef S_ISFIFO - if (S_ISFIFO(st.st_ex_mode)) { - result = 0; - goto done; - } -#endif - - if (st.st_ex_size == len) { - result = 0; - goto done; - } - - if (st.st_ex_size > len) { - /* the sys_ftruncate should have worked */ - goto done; - } - - if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) { - goto done; - } - - result = 0; - - done: - - return result; + WRAP_RETURN(result); } static int cephwrap_fallocate(struct vfs_handle_struct *handle, -- 2.13.7