The branch, master has been updated via 3bb6d441bf0 vfs_ceph_new: common prefix to debug-log messages via d00f20f30f4 vfs_ceph_new: debug-log upon libcephfs low-level calls via 0a8445e891c vfs_ceph_new: use low-level APIs for xattr ops via e714e5ddc50 vfs_ceph_new: use low-level APIs for mknodat via 83011357fb8 vfs_ceph_new: use low-level APIs for renameat via 9a70bd60672 vfs_ceph_new: use low-level APIs for linkat via b536bf1fa87 vfs_ceph_new: use low-level APIs for ftruncate/fallocate via e15586fc609 vfs_ceph_new: use low-level APIs for fsync via 30c1a613fee vfs_ceph_new: use low-level APIs for lseek via 29bbe0f52d4 vfs_ceph_new: use low-level APIs for read/write via 53c9269b219 vfs_ceph_new: use low-level APIs for symlink/readlink via 362a7cf8664 vfs_ceph_new: use low-level APIs for unlinkat via 20b7d2bfe06 vfs_ceph_new: use low-level APIs for fntimes via cb14d3630d8 vfs_ceph_new: use low-level APIs for fchown/fchmod via 24a3423949e vfs_ceph_new: proper error handling to readdir via 99c7179e5da vfs_ceph_new: use low-level APIs for readdir ops via bd955af86e7 vfs_ceph_new: use low-level APIs for mkdirat via a8a7339c6b7 vfs_ceph_new: use low-level APIs for fdopendir via 13671cefffb vfs_ceph_new: use low-level APIs for fstatat via f16183f90ab vfs_ceph_new: use low-level APIs for fstat via 49167684645 vfs_ceph_new: use low-level APIs for open/close via 31085c7efc3 vfs_ceph_new: ref cephmount_cached entry in handle->data via beb21324c9a vfs_ceph_new: use low-level APIs for lchown via 47224fbdeb5 vfs_ceph_new: use low-level APIs for statfs via 93d786b1435 vfs_ceph_new: use low-level APIs for lstat via 1b78d79663c vfs_ceph_new: use low-level APIs for stat via 192b0cf8717 vfs_ceph_new: use low-level APIs for disk_free via 3720452720b vfs_ceph_new: next iteration of samba-to-cephfs bridge from dbc5b73d860 ldb: change the version to 2.11.0 for Samba 4.22
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 3bb6d441bf047bef6d95675057cecd3865a25540 Author: Shachar Sharon <ssha...@redhat.com> Date: Tue Jul 16 14:33:16 2024 +0300 vfs_ceph_new: common prefix to debug-log messages Keep logging consistent: add "[CEPH] " prefix to DBG_DEBUG log messages where missing. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> Autobuild-User(master): Günther Deschner <g...@samba.org> Autobuild-Date(master): Mon Jul 29 15:58:15 UTC 2024 on atb-devel-224 commit d00f20f30f4e77463e82d202099682b7ef68260f Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 26 17:24:37 2024 +0300 vfs_ceph_new: debug-log upon libcephfs low-level calls Add developer's debug-logging upon each call to libcephfs' low-level APIs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 0a8445e891c64d703d44258b2eef85296265c55f Author: Shachar Sharon <ssha...@redhat.com> Date: Sun Jun 23 14:57:10 2024 +0300 vfs_ceph_new: use low-level APIs for xattr ops Implement extended-attributes operations using libcephfs' low-level APIs. Whenever possible, use the open file-handle from fsp-extension to resolve inode-reference and user-permissions. Otherwise, resolve both on-the-fly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit e714e5ddc50a771e743f5e63f686c106abe33b75 Author: Shachar Sharon <ssha...@redhat.com> Date: Sun Jun 23 13:08:25 2024 +0300 vfs_ceph_new: use low-level APIs for mknodat Implement mknodat operations using libcephfs' low-level APIs. Requires parent directory to have valid inode-ref associated with its fsp extension. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 83011357fb834e92505f17d6f65d5f32e3d37ec0 Author: Shachar Sharon <ssha...@redhat.com> Date: Sun Jun 23 12:47:19 2024 +0300 vfs_ceph_new: use low-level APIs for renameat Implement renameat operations using libcephfs' low-level APIs. Requires both directories to have valid inode-ref associated with their fsp extension. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 9a70bd606728110ad91cab547a4e31350010bb68 Author: Shachar Sharon <ssha...@redhat.com> Date: Thu Jun 20 22:46:52 2024 +0300 vfs_ceph_new: use low-level APIs for linkat Implement link operations using libcephfs' low-level APIs. Requires two phase operation: resolve (by-lookup) reference to inode and then do the actual (hard) link operation using parent dir-inode reference to the locally-cached inode. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit b536bf1fa87fb794e2992ab5368f41fdba80e3ad Author: Shachar Sharon <ssha...@redhat.com> Date: Thu Jun 20 14:58:34 2024 +0300 vfs_ceph_new: use low-level APIs for ftruncate/fallocate Implement ftruncate/fallocate operations using libcephfs' low-level APIs. Requires open ceph Fh* associated with fsp (extension). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit e15586fc6097565208011c556282d83eeec2230b Author: Shachar Sharon <ssha...@redhat.com> Date: Thu Jun 20 12:43:39 2024 +0300 vfs_ceph_new: use low-level APIs for fsync Implement fsync operation using libcephfs' low-level APIs. Requires open ceph Fh* associated with fsp (extension). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 30c1a613fee3f625c0559e49e037af9fad04c3b8 Author: Shachar Sharon <ssha...@redhat.com> Date: Thu Jun 20 12:23:03 2024 +0300 vfs_ceph_new: use low-level APIs for lseek Implement lseek operation using libcephfs' low-level APIs. Requires open ceph Fh* associated with fsp (extension). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 29bbe0f52d4ffae9dbb070ffc525acf99203444b Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 19 17:52:45 2024 +0300 vfs_ceph_new: use low-level APIs for read/write Implement read/write IO operations using libcephfs' low-level APIs. Requires open ceph Fh* associated with fsp (extension) to complete both pread/pwrite as well as async I/O operations. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 53c9269b219a54236500d22d8a4c7f2ed582faaf Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 26 13:46:54 2024 +0300 vfs_ceph_new: use low-level APIs for symlink/readlink Implement unlinkat using libcephfs low-level APIs. For readlink operation need to resolve child inode by-lookup and then used the inode reference for the actual low-level readlink. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 362a7cf8664270145bff815347e447797cc1a643 Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 19 14:27:24 2024 +0300 vfs_ceph_new: use low-level APIs for unlinkat Implement unlinkat using libcephfs low-level APIs. Operate using parent directory's open file-handle. When flags has AT_REMOVEDIR bit set call low-level rmdir; otherwise, do normal unlink. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 20b7d2bfe06beefb5e7f091eb317ad18cb53f8a9 Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 19 13:59:53 2024 +0300 vfs_ceph_new: use low-level APIs for fntimes Implement fntimes hook using libcephfs' low-level APIs. Convert smb_file_time to ceph_statx plus proper field mask on-the-fly upon issuing low-level call to libcephfs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit cb14d3630d8c110405c2a43bef15aa31ec4a0fba Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 19 12:48:14 2024 +0300 vfs_ceph_new: use low-level APIs for fchown/fchmod Use libcephfs' low-level APIs to implement 'fchown' and 'fchmod' using open file-handle. If fsp does not have an open cephfs Fh reference, set errno to EBADF and return -1 to VFS. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 24a3423949e127177c019a0d126c6f7523e61984 Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jul 17 11:41:13 2024 +0300 vfs_ceph_new: proper error handling to readdir Error handling in the case of 'ceph_readdir' is done by setting 'errno' deep within libcephfs code. In case of error, emit proper debug message and re-update errno to avoid possible over-write by logging mechanism. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 99c7179e5da6d201f03b1a04dbe2a6722090783d Author: Shachar Sharon <ssha...@redhat.com> Date: Mon Jun 24 13:33:05 2024 +0300 vfs_ceph_new: use low-level APIs for readdir ops Implement readdir and rewinddir operations using libcephfs' low-level APIs. Casts the opaque DIR pointer into struct vfs_ceph_dirp (the first member of struct vfs_ceph_fh) to resolve the ceph_dir_result pointer which libcephfs expects for readdir operations. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit bd955af86e71fa6c87648e578890ea6f4d490d4b Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 19 11:55:27 2024 +0300 vfs_ceph_new: use low-level APIs for mkdirat Implement 'mkdirat' hook using libcephfs' low-level APIs, via the open file-handle reference to parent directory. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit a8a7339c6b7a6866399fd6c409228267a585740f Author: Shachar Sharon <ssha...@redhat.com> Date: Tue Jun 18 17:20:59 2024 +0300 vfs_ceph_new: use low-level APIs for fdopendir Implement fdopendir using libcephfs low-level API and cached (via fsp) open file-handle. Embed the result within cached vfs_ceph_fh so it may be used properly by closedir. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 13671cefffb268d84c973583669681318a2ce3bb Author: Shachar Sharon <ssha...@redhat.com> Date: Wed Jun 19 12:35:11 2024 +0300 vfs_ceph_new: use low-level APIs for fstatat Use libcephfs' low-level APIs to do lookup-by-name via parent's open reference followed by getattr on the inode itself. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit f16183f90abba3c2d3d26262926f1454275a9d3f Author: Shachar Sharon <ssha...@redhat.com> Date: Mon Jun 24 11:39:43 2024 +0300 vfs_ceph_new: use low-level APIs for fstat Use libcephfs' low-level APIs and apply the same logic as stat, but via explicit inode-reference. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 491676846458980944b76d1693726627a9a32503 Author: Shachar Sharon <ssha...@redhat.com> Date: Tue Jun 18 15:02:52 2024 +0300 vfs_ceph_new: use low-level APIs for open/close Implement openat, close and closedir and hooks using libcephfs' low-level APIs. Cache the open Fh* from libcephfs and its related meta-data using VFS fsp-extension mechanism. Upon open-create of new vfs_ceph_fh store the caller credentials (ceph's UserPerm*) within the same context object for subsequent calls. In addition, provide a "pseudo" fd numbering which is reported back to VFS layer and used as debugging hints. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 31085c7efc3572bd6200d3d8e49c1e554cdbfbcc Author: Shachar Sharon <ssha...@redhat.com> Date: Tue Jun 18 12:58:52 2024 +0300 vfs_ceph_new: ref cephmount_cached entry in handle->data Allow direct access to ceph-mount cached-entry via 'handle->data' private pointer. Required in order to allow more complex cached-state with each cephfs mount. Users should now use the local-helper function 'cmount_of' to access the underlying ceph_mount_info. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit beb21324c9a554f50d8d99af2a1b7fe8a17c8ebb Author: Shachar Sharon <ssha...@redhat.com> Date: Mon Jun 17 16:59:05 2024 +0300 vfs_ceph_new: use low-level APIs for lchown Use libcephfs' low-level API ceph_ll_setattr to implement VFS lchown_fn hook. Use to standard pattern of iget/iput to allow operation by Inode reference. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 47224fbdeb55100cf8a7ee75e13b954ab71fc158 Author: Shachar Sharon <ssha...@redhat.com> Date: Mon Jun 17 18:02:07 2024 +0300 vfs_ceph_new: use low-level APIs for statfs BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 93d786b14358db5664e13b1aa43f3f03e7cf0be3 Author: Shachar Sharon <ssha...@redhat.com> Date: Mon Jun 17 15:57:42 2024 +0300 vfs_ceph_new: use low-level APIs for lstat Use libcephfs' low-level APIs and apply the same logic as stat, but using AT_SYMLINK_NOFOLLOW flags. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 1b78d79663c48aa4b6810a875427de85ae49a2e8 Author: Shachar Sharon <ssha...@redhat.com> Date: Mon Jun 17 12:11:18 2024 +0300 vfs_ceph_new: use low-level APIs for stat Start migrating to libcephfs' low-level APIs, using explicit Inode* reference. Implement the VFS 'stat' hook using a ceph_ll_getattr function, encapsulated with a pair of iget/iput to hold a pinned-to-cache Inode* instance. Upon calling to libcephfs this new code crates and destroys on-the-fly a Ceph UserPerm instance based on the uig, gid and groups from 'handle->conn->session_info->unix_token'. This logic ensures that the correct caller-credentials are passed-on to cephfs (instead of those set upon connection-creation in legacy 'vfs_ceph.c'). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 192b0cf8717d79197b985539c9db8ca07a89c570 Author: Shachar Sharon <ssha...@redhat.com> Date: Sun Jun 16 14:50:08 2024 +0300 vfs_ceph_new: use low-level APIs for disk_free Start using libcephfs low-level APIs: get reference to root inode and use it to query statfs. Requires an explicit put-inode to avoid resource leakage by libcephfs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> commit 3720452720b4760509875f0d2a8ed0d104bb1844 Author: Shachar Sharon <ssha...@redhat.com> Date: Thu Jun 13 15:54:48 2024 +0300 vfs_ceph_new: next iteration of samba-to-cephfs bridge Defined new module 'vfs_ceph_new.c' which serves as a place holder for the next development phase of the bridge between samba's VFS layer and libcephfs. Begin with a module which is almost identical to existing 'vfs_ceph.c', except for hooks-names prefix which is 'vfs_ceph_' in order to make clear distinction from existing code base. Following commits will also switch to low-level APIs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686 Signed-off-by: Shachar Sharon <ssha...@redhat.com> Reviewed-by: Guenther Deschner <g...@samba.org> Reviewed-by: Anoop C S <anoo...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/modules/vfs_ceph_new.c | 3117 ++++++++++++++++++++++++++++++++++++++++ source3/modules/wscript_build | 10 + source3/wscript | 1 + 3 files changed, 3128 insertions(+) create mode 100644 source3/modules/vfs_ceph_new.c Changeset truncated at 500 lines: diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c new file mode 100644 index 00000000000..3c82730f87c --- /dev/null +++ b/source3/modules/vfs_ceph_new.c @@ -0,0 +1,3117 @@ +/* + Unix SMB/CIFS implementation. + Wrap disk only vfs functions to sidestep dodgy compilers. + Copyright (C) Tim Potter 1998 + Copyright (C) Jeremy Allison 2007 + Copyright (C) Brian Chrisman 2011 <bchris...@gmail.com> + Copyright (C) Richard Sharpe 2011 <realrichardsha...@gmail.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * This VFS only works with the libcephfs.so user-space client. It is not needed + * if you are using the kernel client or the FUSE client. + * + * Add the following smb.conf parameter to each share that will be hosted on + * Ceph: + * + * vfs objects = [any others you need go here] ceph_new + */ + +#include "includes.h" +#include "smbd/smbd.h" +#include "system/filesys.h" +#include <dirent.h> +#include <sys/statvfs.h> +#include "cephfs/libcephfs.h" +#include "smbprofile.h" +#include "modules/posixacl_xattr.h" +#include "lib/util/tevent_unix.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +#ifndef LIBCEPHFS_VERSION +#define LIBCEPHFS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra) +#define LIBCEPHFS_VERSION_CODE LIBCEPHFS_VERSION(0, 0, 0) +#endif + +/* + * Use %llu whenever we have a 64bit unsigned int, and cast to (long long + * unsigned) + */ +#define llu(_var) ((long long unsigned)_var) + +/* + * Note, libcephfs's return code model is to return -errno. Thus we have to + * convert to what Samba expects: set errno to non-negative value and return -1. + * + * Using convenience helper functions to avoid non-hygienic macro. + */ +static int status_code(int ret) +{ + if (ret < 0) { + errno = -ret; + return -1; + } + errno = 0; + return ret; +} + +static ssize_t lstatus_code(intmax_t ret) +{ + if (ret < 0) { + errno = -((int)ret); + return -1; + } + errno = 0; + return (ssize_t)ret; +} + +/* + * Track unique connections, as virtual mounts, to cephfs file systems. + * Individual mount-entries will be set on the handle->data attribute, but + * the mounts themselves will be shared so as not to spawn extra mounts + * to the same cephfs. + * + * Individual mounts are IDed by a 'cookie' value that is a string built + * from identifying parameters found in smb.conf. + */ + +static struct cephmount_cached { + char *cookie; + uint32_t count; + struct ceph_mount_info *mount; + struct cephmount_cached *next, *prev; + uint64_t fd_index; +} *cephmount_cached; + +static int cephmount_cache_add(const char *cookie, + struct ceph_mount_info *mount, + struct cephmount_cached **out_entry) +{ + struct cephmount_cached *entry = NULL; + + entry = talloc_zero(NULL, struct cephmount_cached); + if (entry == NULL) { + errno = ENOMEM; + return -1; + } + + entry->cookie = talloc_strdup(entry, cookie); + if (entry->cookie == NULL) { + talloc_free(entry); + errno = ENOMEM; + return -1; + } + + entry->mount = mount; + entry->count = 1; + + DBG_DEBUG("[CEPH] adding mount cache entry for %s\n", entry->cookie); + DLIST_ADD(cephmount_cached, entry); + + *out_entry = entry; + return 0; +} + +static struct cephmount_cached *cephmount_cache_update(const char *cookie) +{ + struct cephmount_cached *entry = NULL; + + for (entry = cephmount_cached; entry; entry = entry->next) { + if (strcmp(entry->cookie, cookie) == 0) { + entry->count++; + DBG_DEBUG("[CEPH] updated mount cache: count is [%" + PRIu32 "]\n", entry->count); + return entry; + } + } + + errno = ENOENT; + return NULL; +} + +static int cephmount_cache_remove(struct cephmount_cached *entry) +{ + if (--entry->count) { + DBG_DEBUG("[CEPH] updated mount cache: count is [%" + PRIu32 "]\n", entry->count); + return entry->count; + } + + DBG_DEBUG("[CEPH] removing mount cache entry for %s\n", entry->cookie); + DLIST_REMOVE(cephmount_cached, entry); + talloc_free(entry); + return 0; +} + +static char *cephmount_get_cookie(TALLOC_CTX * mem_ctx, const int snum) +{ + const char *conf_file = + lp_parm_const_string(snum, "ceph", "config_file", "."); + const char *user_id = lp_parm_const_string(snum, "ceph", "user_id", ""); + const char *fsname = + lp_parm_const_string(snum, "ceph", "filesystem", ""); + return talloc_asprintf(mem_ctx, "(%s/%s/%s)", conf_file, user_id, + fsname); +} + +static int cephmount_select_fs(struct ceph_mount_info *mnt, const char *fsname) +{ + /* + * ceph_select_filesystem was added in ceph 'nautilus' (v14). + * Earlier versions of libcephfs will lack that API function. + * At the time of this writing (Feb 2023) all versions of ceph + * supported by ceph upstream have this function. + */ +#if defined(HAVE_CEPH_SELECT_FILESYSTEM) + DBG_DEBUG("[CEPH] calling: ceph_select_filesystem with %s\n", fsname); + return ceph_select_filesystem(mnt, fsname); +#else + DBG_ERR("[CEPH] ceph_select_filesystem not available\n"); + return -ENOTSUP; +#endif +} + +static struct ceph_mount_info *cephmount_mount_fs(const int snum) +{ + int ret; + char buf[256]; + struct ceph_mount_info *mnt = NULL; + /* if config_file and/or user_id are NULL, ceph will use defaults */ + const char *conf_file = + lp_parm_const_string(snum, "ceph", "config_file", NULL); + const char *user_id = + lp_parm_const_string(snum, "ceph", "user_id", NULL); + const char *fsname = + lp_parm_const_string(snum, "ceph", "filesystem", NULL); + + DBG_DEBUG("[CEPH] calling: ceph_create\n"); + ret = ceph_create(&mnt, user_id); + if (ret) { + errno = -ret; + return NULL; + } + + DBG_DEBUG("[CEPH] calling: ceph_conf_read_file with %s\n", + (conf_file == NULL ? "default path" : conf_file)); + ret = ceph_conf_read_file(mnt, conf_file); + if (ret) { + goto err_cm_release; + } + + DBG_DEBUG("[CEPH] calling: ceph_conf_get\n"); + ret = ceph_conf_get(mnt, "log file", buf, sizeof(buf)); + if (ret < 0) { + goto err_cm_release; + } + + /* libcephfs disables POSIX ACL support by default, enable it... */ + ret = ceph_conf_set(mnt, "client_acl_type", "posix_acl"); + if (ret < 0) { + goto err_cm_release; + } + /* tell libcephfs to perform local permission checks */ + ret = ceph_conf_set(mnt, "fuse_default_permissions", "false"); + if (ret < 0) { + goto err_cm_release; + } + /* + * select a cephfs file system to use: + * In ceph, multiple file system support has been stable since + * 'pacific'. Permit different shares to access different file systems. + */ + if (fsname != NULL) { + ret = cephmount_select_fs(mnt, fsname); + if (ret < 0) { + goto err_cm_release; + } + } + + DBG_DEBUG("[CEPH] calling: ceph_mount\n"); + ret = ceph_mount(mnt, NULL); + if (ret >= 0) { + goto cm_done; + } + + err_cm_release: + ceph_release(mnt); + mnt = NULL; + DBG_DEBUG("[CEPH] Error mounting fs: %s\n", strerror(-ret)); + cm_done: + /* + * Handle the error correctly. Ceph returns -errno. + */ + if (ret) { + errno = -ret; + } + return mnt; +} + +/* Check for NULL pointer parameters in vfs_ceph_* functions */ + +/* We don't want to have NULL function pointers lying around. Someone + is sure to try and execute them. These stubs are used to prevent + this possibility. */ + +static int vfs_ceph_connect(struct vfs_handle_struct *handle, + const char *service, const char *user) +{ + int ret = 0; + struct cephmount_cached *entry = NULL; + struct ceph_mount_info *cmount = NULL; + int snum = SNUM(handle->conn); + char *cookie = cephmount_get_cookie(handle, snum); + if (cookie == NULL) { + return -1; + } + + entry = cephmount_cache_update(cookie); + if (entry != NULL) { + goto connect_ok; + } + + cmount = cephmount_mount_fs(snum); + if (cmount == NULL) { + ret = -1; + goto connect_fail; + } + ret = cephmount_cache_add(cookie, cmount, &entry); + if (ret != 0) { + goto connect_fail; + } + +connect_ok: + handle->data = entry; + DBG_WARNING("Connection established with the server: %s\n", cookie); + + /* + * Unless we have an async implementation of getxattrat turn this off. + */ + lp_do_parameter(SNUM(handle->conn), "smbd async dosmode", "false"); +connect_fail: + talloc_free(cookie); + return ret; +} + +static struct ceph_mount_info *cmount_of(const struct vfs_handle_struct *handle) +{ + const struct cephmount_cached *entry = handle->data; + + return entry->mount; +} + +static void vfs_ceph_disconnect(struct vfs_handle_struct *handle) +{ + struct ceph_mount_info *cmount = cmount_of(handle); + int ret = 0; + + ret = cephmount_cache_remove(handle->data); + if (ret > 0) { + DBG_DEBUG("[CEPH] mount cache entry still in use\n"); + return; + } + + ret = ceph_unmount(cmount); + if (ret < 0) { + DBG_ERR("[CEPH] failed to unmount: %s\n", strerror(-ret)); + } + + ret = ceph_release(cmount); + if (ret < 0) { + DBG_ERR("[CEPH] failed to release: %s\n", strerror(-ret)); + } + handle->data = NULL; +} + +/* Ceph user-credentials */ +static struct UserPerm *vfs_ceph_userperm_new( + const struct vfs_handle_struct *handle) +{ + const struct security_unix_token *unix_token = NULL; + + unix_token = get_current_utok(handle->conn); + return ceph_userperm_new(unix_token->uid, + unix_token->gid, + unix_token->ngroups, + unix_token->groups); +} + +static void vfs_ceph_userperm_del(struct UserPerm *uperm) +{ + if (uperm != NULL) { + ceph_userperm_destroy(uperm); + } +} + +/* Ceph's statx to Samba's stat_ex */ +#define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS | CEPH_STATX_BTIME) + +static void smb_stat_from_ceph_statx(SMB_STRUCT_STAT *st, + const struct ceph_statx *stx) +{ + ZERO_STRUCTP(st); + + st->st_ex_dev = stx->stx_dev; + st->st_ex_rdev = stx->stx_rdev; + st->st_ex_ino = stx->stx_ino; + st->st_ex_mode = stx->stx_mode; + st->st_ex_uid = stx->stx_uid; + st->st_ex_gid = stx->stx_gid; + st->st_ex_size = stx->stx_size; + st->st_ex_nlink = stx->stx_nlink; + st->st_ex_atime = stx->stx_atime; + st->st_ex_btime = stx->stx_btime; + st->st_ex_ctime = stx->stx_ctime; + st->st_ex_mtime = stx->stx_mtime; + st->st_ex_blksize = stx->stx_blksize; + st->st_ex_blocks = stx->stx_blocks; +} + +/* Ceph's inode + ino-number */ +struct vfs_ceph_iref { + struct Inode *inode; + uint64_t ino; /* for debug printing */ + bool owner; /* indicate when actual owner of Inode ref */ +}; + +/* Ceph DIR pointer wrapper */ +struct vfs_ceph_dirp { + struct ceph_dir_result *cdr; +}; + +/* Ceph file-handles via fsp-extension */ +struct vfs_ceph_fh { + struct vfs_ceph_dirp dirp; /* keep first for up-casting */ + struct cephmount_cached *cme; + struct UserPerm *uperm; + struct files_struct *fsp; + struct vfs_ceph_iref iref; + struct Fh *fh; + int fd; +}; + +static int cephmount_next_fd(struct cephmount_cached *cme) +{ + /* + * Those file-descriptor numbers are reported back to VFS layer + * (debug-hints only). Using numbers within a large range of + * [1000, 1001000], thus the chances of (annoying but harmless) + * collision are low. + */ + uint64_t next; + + next = (cme->fd_index++ % 1000000) + 1000; + return (int)next; +} + +static int vfs_ceph_release_fh(struct vfs_ceph_fh *cfh) +{ + int ret = 0; + + if (cfh->fh != NULL) { + DBG_DEBUG("[ceph] ceph_ll_close: fd=%d\n", cfh->fd); + ret = ceph_ll_close(cfh->cme->mount, cfh->fh); + cfh->fh = NULL; + } + if (cfh->iref.inode != NULL) { + DBG_DEBUG("[ceph] ceph_ll_put: ino=%" PRIu64 "\n", + cfh->iref.ino); + ceph_ll_put(cfh->cme->mount, cfh->iref.inode); + cfh->iref.inode = NULL; + } + if (cfh->uperm != NULL) { + vfs_ceph_userperm_del(cfh->uperm); + cfh->uperm = NULL; + } + cfh->fd = -1; + + return ret; +} + +static void vfs_ceph_fsp_ext_destroy_cb(void *p_data) +{ + vfs_ceph_release_fh((struct vfs_ceph_fh *)p_data); +} + +static int vfs_ceph_add_fh(struct vfs_handle_struct *handle, + files_struct *fsp, + struct vfs_ceph_fh **out_cfh) +{ + struct cephmount_cached *cme = handle->data; + struct UserPerm *uperm = NULL; + + uperm = vfs_ceph_userperm_new(handle); + if (uperm == NULL) { + return -ENOMEM; + } + + *out_cfh = VFS_ADD_FSP_EXTENSION(handle, + fsp, + struct vfs_ceph_fh, + vfs_ceph_fsp_ext_destroy_cb); + if (*out_cfh == NULL) { + vfs_ceph_userperm_del(uperm); + return -ENOMEM; + } + (*out_cfh)->cme = cme; + (*out_cfh)->uperm = uperm; + (*out_cfh)->fsp = fsp; + (*out_cfh)->fd = -1; + return 0; +} + +static void vfs_ceph_remove_fh(struct vfs_handle_struct *handle, + struct files_struct *fsp) +{ + VFS_REMOVE_FSP_EXTENSION(handle, fsp); +} + +static int vfs_ceph_fetch_fh(struct vfs_handle_struct *handle, + const struct files_struct *fsp, + struct vfs_ceph_fh **out_cfh) +{ + *out_cfh = VFS_FETCH_FSP_EXTENSION(handle, fsp); + return (*out_cfh == NULL) ? -EBADF : 0; +} + +static int vfs_ceph_fetch_io_fh(struct vfs_handle_struct *handle, + const struct files_struct *fsp, + struct vfs_ceph_fh **out_cfh) +{ -- Samba Shared Repository