ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION

FS_ATTRIBUTE_INFORMATION responses have always reported
FILE_CASE_SENSITIVE_SEARCH and FILE_CASE_PRESERVED_NAMES
unconditionally. Case-insensitive filesystems like exFAT, and
casefolded directories on ext4 or f2fs, have no way to signal
their actual semantics to SMB clients.

Now that filesystems expose case behavior through ->fileattr_get,
query it via vfs_fileattr_get() and translate the FS_XFLAG_CASEFOLD
and FS_XFLAG_CASENONPRESERVING flags into the corresponding SMB
attributes. Filesystems without ->fileattr_get continue reporting
default POSIX behavior (case-sensitive, case-preserving).

SMB's FS_ATTRIBUTE_INFORMATION reports per-share attributes from
the share root, not per-file. Shares mixing casefold and
non-casefold directories report the root directory's behavior.

Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://patch.msgid.link/20260507-case-sensitivity-v14-15-e62cc8200435@oracle.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Chuck Lever
2026-05-07 04:53:08 -04:00
committed by Christian Brauner
parent 01ee7c3d2e
commit 0164df1d1d

View File

@@ -14,6 +14,7 @@
#include <linux/falloc.h>
#include <linux/mount.h>
#include <linux/filelock.h>
#include <linux/fileattr.h>
#include "glob.h"
#include "smbfsctl.h"
@@ -5542,16 +5543,33 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
case FS_ATTRIBUTE_INFORMATION:
{
FILE_SYSTEM_ATTRIBUTE_INFO *info;
struct file_kattr fa = {};
size_t sz;
u32 attrs;
int err;
info = (FILE_SYSTEM_ATTRIBUTE_INFO *)rsp->Buffer;
info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS |
FILE_PERSISTENT_ACLS |
FILE_UNICODE_ON_DISK |
FILE_CASE_PRESERVED_NAMES |
FILE_CASE_SENSITIVE_SEARCH |
FILE_SUPPORTS_BLOCK_REFCOUNTING);
attrs = FILE_SUPPORTS_OBJECT_IDS |
FILE_PERSISTENT_ACLS |
FILE_UNICODE_ON_DISK |
FILE_SUPPORTS_BLOCK_REFCOUNTING;
err = vfs_fileattr_get(path.dentry, &fa);
/*
* -EINVAL, -EOPNOTSUPP: ntfs-3g and other FUSE
* filesystems that lack FS_IOC_FSGETXATTR support.
*/
if (err && err != -ENOIOCTLCMD && err != -ENOTTY &&
err != -EINVAL && err != -EOPNOTSUPP) {
path_put(&path);
return err;
}
if (!(fa.fsx_xflags & FS_XFLAG_CASEFOLD))
attrs |= FILE_CASE_SENSITIVE_SEARCH;
if (!(fa.fsx_xflags & FS_XFLAG_CASENONPRESERVING))
attrs |= FILE_CASE_PRESERVED_NAMES;
info->Attributes = cpu_to_le32(attrs);
info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
if (test_share_config_flag(work->tcon->share_conf,