From 09f3bbd41758fb402261121e6f3ffff52171b470 Mon Sep 17 00:00:00 2001 From: Xavi Hernandez Date: Tue, 4 Mar 2025 12:48:41 +0100 Subject: [PATCH] vfs_ceph_new: detect case sensitivity in CephFS MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit CephFS has recently added support for case insensitive access to the file system. This modification detects whether the shared volume is case sensitive or not and reports the FILE_CASE_SENSITIVE_SEARCH capability accordingly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15822 Signed-off-by: Xavi Hernandez Reviewed-by: Anoop C S Reviewed-by: Guenther Deschner Autobuild-User(master): Günther Deschner Autobuild-Date(master): Tue Mar 11 20:34:26 UTC 2025 on atb-devel-224 (cherry picked from commit a52602030e6ba0e1bcddf5f611464b58076fadd0) --- source3/modules/vfs_ceph_new.c | 84 +++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c index 05c2a72d57f..4f1849b3ed5 100644 --- a/source3/modules/vfs_ceph_new.c +++ b/source3/modules/vfs_ceph_new.c @@ -113,6 +113,15 @@ struct vfs_ceph_config { enum vfs_cephfs_proxy_mode proxy; void *libhandle; + /* + * This field stores the Samba capabilities for the share represented + * by this struct. The share capabilities are computed once during the + * module startup and then cached here for future references. + * + * It's completely independent of the CephFS capabilities concept. + */ + uint32_t capabilities; + CEPH_FN(ceph_ll_walk); CEPH_FN(ceph_ll_getattr); CEPH_FN(ceph_ll_setattr); @@ -1932,12 +1941,79 @@ static uint64_t vfs_ceph_disk_free(struct vfs_handle_struct *handle, return *dfree; } +static int vfs_ceph_check_case_sensitivity(struct vfs_handle_struct *handle, + uint32_t *capabilities) +{ + struct vfs_ceph_iref iref = {0}; + char value[8] = {0}; + struct vfs_ceph_config *config = NULL; + uint32_t caps; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct vfs_ceph_config, + return -ENOMEM); + + if (config->capabilities != 0) { + *capabilities = config->capabilities; + return 0; + } + + /* + * In CephFS, case sensitivity configuration is inherited by default, + * but it can be manually overridden by an administrator. Samba assumes + * that all directories inherit the configuration from the root of the + * share and the administrator doesn't change it manually. + */ + ret = vfs_ceph_iget(handle, handle->conn->connectpath, 0, &iref); + if (ret != 0) { + return ret; + } + + caps = FILE_CASE_PRESERVED_NAMES; + + ret = vfs_ceph_ll_getxattr(handle, &iref, "ceph.dir.casesensitive", + value, sizeof(value) - 1); + if (ret < 0) { + if (ret != -ENODATA) { + DBG_ERR("[CEPH] failed to get case sensitivity " + "settings: path='%s' %s", + handle->conn->connectpath, strerror(-ret)); + goto out; + } + + /* + * The xattr is not defined, so the filesystem is case sensitive + * by default. + */ + caps |= FILE_CASE_SENSITIVE_SEARCH; + } else { + /* + * We only accept "0" as 'false' (as defined in the CephFS + * documentation). All other values are interpreted as 'true' + */ + if (strcmp(value, "0") != 0) { + caps |= FILE_CASE_SENSITIVE_SEARCH; + } + } + + config->capabilities = caps; + *capabilities = caps; + + ret = 0; + +out: + vfs_ceph_iput(handle, &iref); + + return ret; +} + static int vfs_ceph_statvfs(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, struct vfs_statvfs_struct *statbuf) { struct statvfs statvfs_buf = { 0 }; struct vfs_ceph_iref iref = {0}; + uint32_t caps = 0; int ret; ret = vfs_ceph_iget(handle, smb_fname->base_name, 0, &iref); @@ -1950,6 +2026,11 @@ static int vfs_ceph_statvfs(struct vfs_handle_struct *handle, goto out; } + ret = vfs_ceph_check_case_sensitivity(handle, &caps); + if (ret < 0) { + goto out; + } + statbuf->OptimalTransferSize = statvfs_buf.f_frsize; statbuf->BlockSize = statvfs_buf.f_bsize; statbuf->TotalBlocks = statvfs_buf.f_blocks; @@ -1958,8 +2039,7 @@ static int vfs_ceph_statvfs(struct vfs_handle_struct *handle, statbuf->TotalFileNodes = statvfs_buf.f_files; statbuf->FreeFileNodes = statvfs_buf.f_ffree; statbuf->FsIdentifier = statvfs_buf.f_fsid; - statbuf->FsCapabilities = - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; + statbuf->FsCapabilities = caps; DBG_DEBUG("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, " "f_bavail: %ld\n", -- 2.47.2