From: Chuck Lever <[email protected]>

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 <[email protected]>
Reviewed-by: Roland Mainz <[email protected]>
Signed-off-by: Chuck Lever <[email protected]>
---
 fs/smb/server/smb2pdu.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index ee32e61b6d3c..cf0bc453a036 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -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"
@@ -5541,16 +5542,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,

-- 
2.53.0



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to