From 46cf7c101b198b06d8497b36739a92d33ad53b05 Mon Sep 17 00:00:00 2001 From: Shachar Sharon Date: Mon, 13 Nov 2023 15:47:24 +0200 Subject: [PATCH] vfs_ceph: use extra 'ceph_*at()' calls when available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of libcephfs version-10.0.3 the high-level API has few more '*at()' calls. Prefer those newer hooks over path-based when having an appropriate directory fd (namely: ceph_mkdirat, ceph_openat, cepth_unlinkat, ceph_symlinkat, ceph_readlinkat). Ceph commit: https://github.com/ceph/ceph/commit/3831aa12f3067d8cc362f39f7136dd53cb946d22 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15516 Signed-off-by: Shachar Sharon Reviewed-by: Gunther Deschner Reviewed-by: Anoop C S Autobuild-User(master): Günther Deschner Autobuild-Date(master): Thu Jan 4 21:09:54 UTC 2024 on atb-devel-224 (cherry picked from commit 7e0a18acde8ea4801ad4f56a0b2d8daa2120f6e5) --- source3/modules/vfs_ceph.c | 132 +++++++++++++++++++++++++++++++------ source3/wscript | 10 +++ 2 files changed, 121 insertions(+), 21 deletions(-) diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 353183fa0bb..4d47d7aeed6 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -473,8 +473,22 @@ static int cephwrap_mkdirat(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, mode_t mode) { + int result = -1; +#ifdef HAVE_CEPH_MKDIRAT + int dirfd = fsp_get_pathref_fd(dirfsp); + + DBG_DEBUG("[CEPH] mkdirat(%p, %d, %s)\n", + handle, + dirfd, + smb_fname->base_name); + + result = ceph_mkdirat(handle->data, dirfd, smb_fname->base_name, mode); + + DBG_DEBUG("[CEPH] mkdirat(...) = %d\n", result); + + WRAP_RETURN(result); +#else struct smb_filename *full_fname = NULL; - int result; full_fname = full_path_from_dirfsp_atname(talloc_tos(), dirfsp, @@ -490,7 +504,8 @@ static int cephwrap_mkdirat(struct vfs_handle_struct *handle, TALLOC_FREE(full_fname); - return WRAP_RETURN(result); + WRAP_RETURN(result); +#endif } static int cephwrap_closedir(struct vfs_handle_struct *handle, DIR *dirp) @@ -517,15 +532,44 @@ static int cephwrap_openat(struct vfs_handle_struct *handle, bool have_opath = false; bool became_root = false; int result = -ENOENT; +#ifdef HAVE_CEPH_OPENAT + int dirfd = -1; +#endif if (how->resolve != 0) { errno = ENOSYS; return -1; } - /* - * ceph doesn't have openat(). - */ + if (smb_fname->stream_name) { + goto out; + } + +#ifdef O_PATH + have_opath = true; + if (fsp->fsp_flags.is_pathref) { + flags |= O_PATH; + } +#endif + +#ifdef HAVE_CEPH_OPENAT + dirfd = fsp_get_pathref_fd(dirfsp); + + DBG_DEBUG("[CEPH] openat(%p, %d, %p, %d, %d)\n", + handle, dirfd, fsp, flags, mode); + + if (fsp->fsp_flags.is_pathref && !have_opath) { + become_root(); + became_root = true; + } + + result = ceph_openat(handle->data, + dirfd, + smb_fname->base_name, + flags, + mode); + +#else if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) { name = full_path_from_dirfsp_atname(talloc_tos(), dirfsp, @@ -539,28 +583,16 @@ static int cephwrap_openat(struct vfs_handle_struct *handle, DBG_DEBUG("[CEPH] openat(%p, %s, %p, %d, %d)\n", handle, smb_fname_str_dbg(smb_fname), fsp, flags, mode); - if (smb_fname->stream_name) { - goto out; - } - -#ifdef O_PATH - have_opath = true; - if (fsp->fsp_flags.is_pathref) { - flags |= O_PATH; - } -#endif - if (fsp->fsp_flags.is_pathref && !have_opath) { become_root(); became_root = true; } result = ceph_open(handle->data, smb_fname->base_name, flags, mode); - +#endif if (became_root) { unbecome_root(); } - out: TALLOC_FREE(name); fsp->fsp_flags.have_proc_fds = false; @@ -992,8 +1024,28 @@ static int cephwrap_unlinkat(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, int flags) { - struct smb_filename *full_fname = NULL; int result = -1; +#ifdef HAVE_CEPH_UNLINKAT + int dirfd = fsp_get_pathref_fd(dirfsp); + + DBG_DEBUG("[CEPH] unlinkat(%p, %d, %s)\n", + handle, + dirfd, + smb_fname_str_dbg(smb_fname)); + + if (smb_fname->stream_name) { + errno = ENOENT; + return result; + } + + result = ceph_unlinkat(handle->data, + dirfd, + smb_fname->base_name, + flags); + DBG_DEBUG("[CEPH] unlinkat(...) = %d\n", result); + WRAP_RETURN(result); +#else + struct smb_filename *full_fname = NULL; DBG_DEBUG("[CEPH] unlink(%p, %s)\n", handle, @@ -1019,6 +1071,7 @@ static int cephwrap_unlinkat(struct vfs_handle_struct *handle, TALLOC_FREE(full_fname); DBG_DEBUG("[CEPH] unlink(...) = %d\n", result); WRAP_RETURN(result); +#endif } static int cephwrap_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode) @@ -1225,8 +1278,24 @@ static int cephwrap_symlinkat(struct vfs_handle_struct *handle, struct files_struct *dirfsp, const struct smb_filename *new_smb_fname) { - struct smb_filename *full_fname = NULL; int result = -1; +#ifdef HAVE_CEPH_SYMLINKAT + int dirfd = fsp_get_pathref_fd(dirfsp); + + DBG_DEBUG("[CEPH] symlinkat(%p, %s, %d, %s)\n", + handle, + link_target->base_name, + dirfd, + new_smb_fname->base_name); + + result = ceph_symlinkat(handle->data, + link_target->base_name, + dirfd, + new_smb_fname->base_name); + DBG_DEBUG("[CEPH] symlinkat(...) = %d\n", result); + WRAP_RETURN(result); +#else + struct smb_filename *full_fname = NULL; full_fname = full_path_from_dirfsp_atname(talloc_tos(), dirfsp, @@ -1245,6 +1314,7 @@ static int cephwrap_symlinkat(struct vfs_handle_struct *handle, TALLOC_FREE(full_fname); DBG_DEBUG("[CEPH] symlink(...) = %d\n", result); WRAP_RETURN(result); +#endif } static int cephwrap_readlinkat(struct vfs_handle_struct *handle, @@ -1253,8 +1323,27 @@ static int cephwrap_readlinkat(struct vfs_handle_struct *handle, char *buf, size_t bufsiz) { - struct smb_filename *full_fname = NULL; int result = -1; +#ifdef HAVE_CEPH_READLINKAT + int dirfd = fsp_get_pathref_fd(dirfsp); + + DBG_DEBUG("[CEPH] readlinkat(%p, %d, %s, %p, %llu)\n", + handle, + dirfd, + smb_fname->base_name, + buf, + llu(bufsiz)); + + result = ceph_readlinkat(handle->data, + dirfd, + smb_fname->base_name, + buf, + bufsiz); + + DBG_DEBUG("[CEPH] readlinkat(...) = %d\n", result); + WRAP_RETURN(result); +#else + struct smb_filename *full_fname = NULL; full_fname = full_path_from_dirfsp_atname(talloc_tos(), dirfsp, @@ -1270,6 +1359,7 @@ static int cephwrap_readlinkat(struct vfs_handle_struct *handle, TALLOC_FREE(full_fname); DBG_DEBUG("[CEPH] readlink(...) = %d\n", result); WRAP_RETURN(result); +#endif } static int cephwrap_linkat(struct vfs_handle_struct *handle, diff --git a/source3/wscript b/source3/wscript index b7f96f3bf99..ce163af166d 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1683,6 +1683,16 @@ int main(void) { conf.DEFINE('HAVE_CEPH', '1') conf.CHECK_FUNCS_IN('ceph_select_filesystem', 'cephfs', headers='cephfs/libcephfs.h') + conf.CHECK_FUNCS_IN('ceph_mkdirat', 'cephfs', + headers='cephfs/libcephfs.h') + conf.CHECK_FUNCS_IN('ceph_openat', 'cephfs', + headers='cephfs/libcephfs.h') + conf.CHECK_FUNCS_IN('ceph_unlinkat', 'cephfs', + headers='cephfs/libcephfs.h') + conf.CHECK_FUNCS_IN('ceph_symlinkat', 'cephfs', + headers='cephfs/libcephfs.h') + conf.CHECK_FUNCS_IN('ceph_readlinkat', 'cephfs', + headers='cephfs/libcephfs.h') else: Logs.warn('''Ceph support disabled due to --without-acl-support or lack of ceph_statx support''') -- 2.43.0