* [PATCH v3 00/16] Exposing case folding behavior
@ 2026-01-12 17:46 Chuck Lever
2026-01-12 17:46 ` [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr Chuck Lever
` (16 more replies)
0 siblings, 17 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Following on from
https://lore.kernel.org/linux-nfs/20251021-zypressen-bazillus-545a44af57fd@brauner/T/#m0ba197d75b7921d994cf284f3cef3a62abb11aaa
I'm attempting to implement enough support in the Linux VFS to
enable file services like NFSD and ksmbd (and user space
equivalents) to provide the actual status of case folding support
in local file systems. The default behavior for local file systems
not explicitly supported in this series is to reflect the usual
POSIX behaviors:
case-insensitive = false
case-preserving = true
The case-insensitivity and case-preserving booleans can be consumed
immediately by NFSD. These two booleans have been part of the NFSv3
and NFSv4 protocols for decades, in order to support NFS clients on
non-POSIX systems.
Support for user space file servers is why this series exposes case
folding information via a user-space API. I don't know of any other
category of user-space application that requires access to case
folding info.
The Linux NFS community has a growing interest in supporting NFS
clients on Windows and MacOS platforms, where file name behavior does
not align with traditional POSIX semantics.
One example of a Windows-based NFS client is [1]. This client
implementation explicitly requires servers to report
FATTR4_WORD0_CASE_INSENSITIVE = TRUE for proper operation, a hard
requirement for Windows client interoperability because Windows
applications expect case-insensitive behavior. When an NFS client
knows the server is case-insensitive, it can avoid issuing multiple
LOOKUP/READDIR requests to search for case variants, and applications
like Win32 programs work correctly without manual workarounds or
code changes.
Even the Linux client can take advantage of this information. Trond
merged patches 4 years ago [2] that introduce support for case
insensitivity, in support of the Hammerspace NFS server. In
particular, when a client detects a case-insensitive NFS share,
negative dentry caching must be disabled (a lookup for "FILE.TXT"
failing shouldn't cache a negative entry when "file.txt" exists)
and directory change invalidation must clear all cached case-folded
file name variants.
Hammerspace servers and several other NFS server implementations
operate in multi-protocol environments, where a single file service
instance caters to both NFS and SMB clients. In those cases, things
work more smoothly for everyone when the NFS client can see and adapt
to the case folding behavior that SMB users rely on and expect. NFSD
needs to support the case-insensitivity and case-preserving booleans
properly in order to participate as a first-class citizen in such
environments.
Series based on v6.19-rc5.
[1] https://github.com/kofemann/ms-nfs41-client
[2] https://patchwork.kernel.org/project/linux-nfs/cover/20211217203658.439352-1-trondmy@kernel.org/
---
Changes since v2:
- Remove unicode labels
- Replace vfs_get_case_info
- Add support for several more local file system implementations
- Add support for in-kernel SMB server
Changes since RFC:
- Use file_getattr instead of statx
- Postpone exposing Unicode version until later
- Support NTFS and ext4 in addition to FAT
- Support NFSv4 fattr4 in addition to NFSv3 PATHCONF
Chuck Lever (16):
fs: Add case sensitivity info to file_kattr
fat: Implement fileattr_get for case sensitivity
exfat: Implement fileattr_get for case sensitivity
ntfs3: Implement fileattr_get for case sensitivity
hfs: Implement fileattr_get for case sensitivity
hfsplus: Report case sensitivity in fileattr_get
ext4: Report case sensitivity in fileattr_get
xfs: Report case sensitivity in fileattr_get
cifs: Implement fileattr_get for case sensitivity
nfs: Implement fileattr_get for case sensitivity
f2fs: Add case sensitivity reporting to fileattr_get
vboxsf: Implement fileattr_get for case sensitivity
isofs: Implement fileattr_get for case sensitivity
nfsd: Report export case-folding via NFSv3 PATHCONF
nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and
FATTR4_CASE_PRESERVING
ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION
fs/exfat/exfat_fs.h | 2 ++
fs/exfat/file.c | 17 +++++++++++++++--
fs/exfat/namei.c | 1 +
fs/ext4/ioctl.c | 8 ++++++++
fs/f2fs/file.c | 8 ++++++++
fs/fat/fat.h | 3 +++
fs/fat/file.c | 18 ++++++++++++++++++
fs/fat/namei_msdos.c | 1 +
fs/fat/namei_vfat.c | 1 +
fs/file_attr.c | 10 ++++++++++
fs/hfs/dir.c | 1 +
fs/hfs/hfs_fs.h | 2 ++
fs/hfs/inode.c | 13 +++++++++++++
fs/hfsplus/inode.c | 9 +++++++++
fs/isofs/dir.c | 11 +++++++++++
fs/nfs/client.c | 9 +++++++--
fs/nfs/inode.c | 18 ++++++++++++++++++
fs/nfs/internal.h | 3 +++
fs/nfs/nfs3proc.c | 2 ++
fs/nfs/nfs3xdr.c | 7 +++++--
fs/nfs/nfs4proc.c | 2 ++
fs/nfs/proc.c | 3 +++
fs/nfs/symlink.c | 3 +++
fs/nfsd/nfs3proc.c | 18 ++++++++++--------
fs/nfsd/nfs4xdr.c | 30 ++++++++++++++++++++++++++----
fs/nfsd/vfs.c | 25 +++++++++++++++++++++++++
fs/nfsd/vfs.h | 2 ++
fs/ntfs3/file.c | 23 +++++++++++++++++++++++
fs/ntfs3/inode.c | 1 +
fs/ntfs3/namei.c | 2 ++
fs/ntfs3/ntfs_fs.h | 1 +
fs/smb/client/cifsfs.c | 19 +++++++++++++++++++
fs/smb/server/smb2pdu.c | 30 ++++++++++++++++++++++++------
fs/vboxsf/dir.c | 1 +
fs/vboxsf/file.c | 6 ++++--
fs/vboxsf/super.c | 4 ++++
fs/vboxsf/utils.c | 31 +++++++++++++++++++++++++++++++
fs/vboxsf/vfsmod.h | 6 ++++++
fs/xfs/xfs_ioctl.c | 7 +++++++
include/linux/fileattr.h | 3 +++
include/linux/nfs_xdr.h | 2 ++
41 files changed, 337 insertions(+), 26 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 15:21 ` Christoph Hellwig
2026-01-12 17:46 ` [PATCH v3 02/16] fat: Implement fileattr_get for case sensitivity Chuck Lever
` (15 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Enable upper layers such as NFSD to retrieve case sensitivity
information from file systems by adding case_insensitive and
case_preserving boolean fields to struct file_kattr.
The default POSIX behavior (case-sensitive, case-preserving) is
initialized in vfs_fileattr_get(), allowing filesystems to override
these values only when they differ from the default.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/file_attr.c | 10 ++++++++++
include/linux/fileattr.h | 3 +++
2 files changed, 13 insertions(+)
diff --git a/fs/file_attr.c b/fs/file_attr.c
index 13cdb31a3e94..a73de0e0ecac 100644
--- a/fs/file_attr.c
+++ b/fs/file_attr.c
@@ -21,6 +21,9 @@
void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags)
{
memset(fa, 0, sizeof(*fa));
+ /* Default: POSIX semantics (case-sensitive, case-preserving) */
+ fa->case_insensitive = false;
+ fa->case_preserving = true;
fa->fsx_valid = true;
fa->fsx_xflags = xflags;
if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE)
@@ -51,6 +54,9 @@ EXPORT_SYMBOL(fileattr_fill_xflags);
void fileattr_fill_flags(struct file_kattr *fa, u32 flags)
{
memset(fa, 0, sizeof(*fa));
+ /* Default: POSIX semantics (case-sensitive, case-preserving) */
+ fa->case_insensitive = false;
+ fa->case_preserving = true;
fa->flags_valid = true;
fa->flags = flags;
if (fa->flags & FS_SYNC_FL)
@@ -84,6 +90,10 @@ int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
struct inode *inode = d_inode(dentry);
int error;
+ /* Default: POSIX semantics (case-sensitive, case-preserving) */
+ fa->case_insensitive = false;
+ fa->case_preserving = true;
+
if (!inode->i_op->fileattr_get)
return -ENOIOCTLCMD;
diff --git a/include/linux/fileattr.h b/include/linux/fileattr.h
index f89dcfad3f8f..cfd4d3973716 100644
--- a/include/linux/fileattr.h
+++ b/include/linux/fileattr.h
@@ -51,6 +51,9 @@ struct file_kattr {
/* selectors: */
bool flags_valid:1;
bool fsx_valid:1;
+ /* case sensitivity behavior: */
+ bool case_insensitive:1;
+ bool case_preserving:1;
};
int copy_fsxattr_to_user(const struct file_kattr *fa, struct fsxattr __user *ufa);
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 02/16] fat: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
2026-01-12 17:46 ` [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 15:23 ` Christoph Hellwig
2026-01-12 17:46 ` [PATCH v3 03/16] exfat: " Chuck Lever
` (14 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Report FAT's case sensitivity behavior via the file_kattr boolean
fields. FAT filesystems are case-insensitive by default and do not
preserve case at rest (stored names are uppercased).
MSDOS supports a 'nocase' mount option that enables case-sensitive
behavior; check this option when reporting case sensitivity.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/fat/fat.h | 3 +++
fs/fat/file.c | 18 ++++++++++++++++++
fs/fat/namei_msdos.c | 1 +
fs/fat/namei_vfat.c | 1 +
4 files changed, 23 insertions(+)
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index d3e426de5f01..38da08d8fec4 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -10,6 +10,8 @@
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
+struct file_kattr;
+
/*
* vfat shortname flags
*/
@@ -407,6 +409,7 @@ extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
extern int fat_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags);
+extern int fat_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
extern int fat_file_fsync(struct file *file, loff_t start, loff_t end,
int datasync);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 4fc49a614fb8..d26dc792611a 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -16,6 +16,7 @@
#include <linux/fsnotify.h>
#include <linux/security.h>
#include <linux/falloc.h>
+#include <linux/fileattr.h>
#include "fat.h"
static long fat_fallocate(struct file *file, int mode,
@@ -395,6 +396,22 @@ void fat_truncate_blocks(struct inode *inode, loff_t offset)
fat_flush_inodes(inode->i_sb, inode, NULL);
}
+int fat_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
+
+ /*
+ * FAT filesystems do not preserve case: stored names are
+ * uppercased. They are case-insensitive by default, but
+ * MSDOS supports a 'nocase' mount option for case-sensitive
+ * behavior.
+ */
+ fa->case_insensitive = !sbi->options.nocase;
+ fa->case_preserving = false;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fat_fileattr_get);
+
int fat_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask, unsigned int flags)
{
@@ -574,5 +591,6 @@ EXPORT_SYMBOL_GPL(fat_setattr);
const struct inode_operations fat_file_inode_operations = {
.setattr = fat_setattr,
.getattr = fat_getattr,
+ .fileattr_get = fat_fileattr_get,
.update_time = fat_update_time,
};
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 0b920ee40a7f..380add5c6c66 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -640,6 +640,7 @@ static const struct inode_operations msdos_dir_inode_operations = {
.rename = msdos_rename,
.setattr = fat_setattr,
.getattr = fat_getattr,
+ .fileattr_get = fat_fileattr_get,
.update_time = fat_update_time,
};
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 5dbc4cbb8fce..6cf513f97afa 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1180,6 +1180,7 @@ static const struct inode_operations vfat_dir_inode_operations = {
.rename = vfat_rename2,
.setattr = fat_setattr,
.getattr = fat_getattr,
+ .fileattr_get = fat_fileattr_get,
.update_time = fat_update_time,
};
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 03/16] exfat: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
2026-01-12 17:46 ` [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr Chuck Lever
2026-01-12 17:46 ` [PATCH v3 02/16] fat: Implement fileattr_get for case sensitivity Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-14 0:45 ` Namjae Jeon
2026-01-12 17:46 ` [PATCH v3 04/16] ntfs3: " Chuck Lever
` (13 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Report exFAT's case sensitivity behavior via the file_kattr boolean
fields. exFAT is always case-insensitive (using an upcase table for
comparison) and always preserves case at rest.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/exfat/exfat_fs.h | 2 ++
fs/exfat/file.c | 17 +++++++++++++++--
fs/exfat/namei.c | 1 +
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 176fef62574c..11c782a28843 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -468,6 +468,8 @@ int exfat_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
int exfat_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, unsigned int request_mask,
unsigned int query_flags);
+struct file_kattr;
+int exfat_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
int exfat_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
long exfat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
long exfat_compat_ioctl(struct file *filp, unsigned int cmd,
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 536c8078f0c1..0fda71b3e838 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -12,6 +12,7 @@
#include <linux/security.h>
#include <linux/msdos_fs.h>
#include <linux/writeback.h>
+#include <linux/fileattr.h>
#include "exfat_raw.h"
#include "exfat_fs.h"
@@ -281,6 +282,17 @@ int exfat_getattr(struct mnt_idmap *idmap, const struct path *path,
return 0;
}
+int exfat_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ /*
+ * exFAT is always case-insensitive (using upcase table) and
+ * always preserves case at rest.
+ */
+ fa->case_insensitive = true;
+ fa->case_preserving = true;
+ return 0;
+}
+
int exfat_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr)
{
@@ -775,6 +787,7 @@ const struct file_operations exfat_file_operations = {
};
const struct inode_operations exfat_file_inode_operations = {
- .setattr = exfat_setattr,
- .getattr = exfat_getattr,
+ .setattr = exfat_setattr,
+ .getattr = exfat_getattr,
+ .fileattr_get = exfat_fileattr_get,
};
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index dfe957493d49..a3a854ddc83a 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -1323,4 +1323,5 @@ const struct inode_operations exfat_dir_inode_operations = {
.rename = exfat_rename,
.setattr = exfat_setattr,
.getattr = exfat_getattr,
+ .fileattr_get = exfat_fileattr_get,
};
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 04/16] ntfs3: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (2 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 03/16] exfat: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-12 17:46 ` [PATCH v3 05/16] hfs: " Chuck Lever
` (12 subsequent siblings)
16 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Report NTFS case sensitivity behavior via the file_kattr boolean
fields. NTFS always preserves case at rest.
Case sensitivity depends on mount options: with "nocase", NTFS
is case-insensitive; otherwise it is case-sensitive.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/ntfs3/file.c | 23 +++++++++++++++++++++++
fs/ntfs3/inode.c | 1 +
fs/ntfs3/namei.c | 2 ++
fs/ntfs3/ntfs_fs.h | 1 +
4 files changed, 27 insertions(+)
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index 2e7b2e566ebe..cc37a9386d93 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -146,6 +146,28 @@ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg)
}
#endif
+/*
+ * ntfs_fileattr_get - inode_operations::fileattr_get
+ */
+int ntfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ struct inode *inode = d_inode(dentry);
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+
+ /* Avoid any operation if inode is bad. */
+ if (unlikely(is_bad_ni(ntfs_i(inode))))
+ return -EINVAL;
+
+ /*
+ * NTFS preserves case. Case sensitivity depends on mount options:
+ * with "nocase" mount option, NTFS is case-insensitive;
+ * otherwise it is case-sensitive.
+ */
+ fa->case_insensitive = sbi->options && sbi->options->nocase;
+ fa->case_preserving = true;
+ return 0;
+}
+
/*
* ntfs_getattr - inode_operations::getattr
*/
@@ -1460,6 +1482,7 @@ const struct inode_operations ntfs_file_inode_operations = {
.get_acl = ntfs_get_acl,
.set_acl = ntfs_set_acl,
.fiemap = ntfs_fiemap,
+ .fileattr_get = ntfs_fileattr_get,
};
const struct file_operations ntfs_file_operations = {
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index 0a9ac5efeb67..205083e8a6e0 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -2089,6 +2089,7 @@ const struct inode_operations ntfs_link_inode_operations = {
.get_link = ntfs_get_link,
.setattr = ntfs_setattr,
.listxattr = ntfs_listxattr,
+ .fileattr_get = ntfs_fileattr_get,
};
const struct address_space_operations ntfs_aops = {
diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c
index 3b24ca02de61..d09414711016 100644
--- a/fs/ntfs3/namei.c
+++ b/fs/ntfs3/namei.c
@@ -519,6 +519,7 @@ const struct inode_operations ntfs_dir_inode_operations = {
.getattr = ntfs_getattr,
.listxattr = ntfs_listxattr,
.fiemap = ntfs_fiemap,
+ .fileattr_get = ntfs_fileattr_get,
};
const struct inode_operations ntfs_special_inode_operations = {
@@ -527,6 +528,7 @@ const struct inode_operations ntfs_special_inode_operations = {
.listxattr = ntfs_listxattr,
.get_acl = ntfs_get_acl,
.set_acl = ntfs_set_acl,
+ .fileattr_get = ntfs_fileattr_get,
};
const struct dentry_operations ntfs_dentry_ops = {
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index a4559c9f64e6..a578b75f31fc 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -504,6 +504,7 @@ extern const struct file_operations ntfs_dir_operations;
extern const struct file_operations ntfs_legacy_dir_operations;
/* Globals from file.c */
+int ntfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask, u32 flags);
int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 05/16] hfs: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (3 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 04/16] ntfs3: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 17:35 ` Viacheslav Dubeyko
2026-01-12 17:46 ` [PATCH v3 06/16] hfsplus: Report case sensitivity in fileattr_get Chuck Lever
` (11 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Report HFS case sensitivity behavior via the file_kattr boolean
fields. HFS is always case-insensitive (using Mac OS Roman case
folding) and always preserves case at rest.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/hfs/dir.c | 1 +
fs/hfs/hfs_fs.h | 2 ++
fs/hfs/inode.c | 13 +++++++++++++
3 files changed, 16 insertions(+)
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 86a6b317b474..552156896105 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -321,4 +321,5 @@ const struct inode_operations hfs_dir_inode_operations = {
.rmdir = hfs_remove,
.rename = hfs_rename,
.setattr = hfs_inode_setattr,
+ .fileattr_get = hfs_fileattr_get,
};
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index e94dbc04a1e4..a25cdda8ab34 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -177,6 +177,8 @@ extern int hfs_get_block(struct inode *inode, sector_t block,
extern const struct address_space_operations hfs_aops;
extern const struct address_space_operations hfs_btree_aops;
+struct file_kattr;
+int hfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
int hfs_write_begin(const struct kiocb *iocb, struct address_space *mapping,
loff_t pos, unsigned int len, struct folio **foliop,
void **fsdata);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 524db1389737..06429decc1d8 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -18,6 +18,7 @@
#include <linux/uio.h>
#include <linux/xattr.h>
#include <linux/blkdev.h>
+#include <linux/fileattr.h>
#include "hfs_fs.h"
#include "btree.h"
@@ -698,6 +699,17 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
return ret;
}
+int hfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ /*
+ * HFS is always case-insensitive (using Mac OS Roman case
+ * folding) and always preserves case at rest.
+ */
+ fa->case_insensitive = true;
+ fa->case_preserving = true;
+ return 0;
+}
+
static const struct file_operations hfs_file_operations = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
@@ -714,4 +726,5 @@ static const struct inode_operations hfs_file_inode_operations = {
.lookup = hfs_file_lookup,
.setattr = hfs_inode_setattr,
.listxattr = generic_listxattr,
+ .fileattr_get = hfs_fileattr_get,
};
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 06/16] hfsplus: Report case sensitivity in fileattr_get
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (4 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 05/16] hfs: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 17:36 ` Viacheslav Dubeyko
2026-01-12 17:46 ` [PATCH v3 07/16] ext4: " Chuck Lever
` (10 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Add case sensitivity reporting to the existing hfsplus_fileattr_get()
function. HFS+ always preserves case at rest.
Case sensitivity depends on how the volume was formatted: HFSX
volumes may be either case-sensitive or case-insensitive, indicated
by the HFSPLUS_SB_CASEFOLD superblock flag.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/hfsplus/inode.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 7ae6745ca7ae..0ce9561c0f18 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -694,6 +694,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
{
struct inode *inode = d_inode(dentry);
struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+ struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
unsigned int flags = 0;
if (inode->i_flags & S_IMMUTABLE)
@@ -705,6 +706,14 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
fileattr_fill_flags(fa, flags);
+ /*
+ * HFS+ always preserves case. Case sensitivity depends on how
+ * the filesystem was formatted: HFSX volumes may be either
+ * case-sensitive or case-insensitive.
+ */
+ fa->case_insensitive = test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags);
+ fa->case_preserving = true;
+
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 07/16] ext4: Report case sensitivity in fileattr_get
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (5 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 06/16] hfsplus: Report case sensitivity in fileattr_get Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 11:50 ` Jan Kara
2026-01-12 17:46 ` [PATCH v3 08/16] xfs: " Chuck Lever
` (9 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Report ext4's case sensitivity behavior via file_kattr boolean
fields. ext4 always preserves case at rest.
Case sensitivity is a per-directory setting in ext4. If the queried
inode is a casefolded directory, report case-insensitive; otherwise
report case-sensitive (standard POSIX behavior).
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/ext4/ioctl.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 7ce0fc40aec2..653035017c7f 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -996,6 +996,14 @@ int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
if (ext4_has_feature_project(inode->i_sb))
fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
+ /*
+ * ext4 always preserves case. If this inode is a casefolded
+ * directory, report case-insensitive; otherwise report
+ * case-sensitive (standard POSIX behavior).
+ */
+ fa->case_insensitive = IS_CASEFOLDED(inode);
+ fa->case_preserving = true;
+
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 08/16] xfs: Report case sensitivity in fileattr_get
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (6 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 07/16] ext4: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 16:02 ` Darrick J. Wong
2026-01-12 17:46 ` [PATCH v3 09/16] cifs: Implement fileattr_get for case sensitivity Chuck Lever
` (8 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Upper layers such as NFSD need to query whether a filesystem is
case-sensitive. Populate the case_insensitive and case_preserving
fields in xfs_fileattr_get(). XFS always preserves case. XFS is
case-sensitive by default, but supports ASCII case-insensitive
lookups when formatted with the ASCIICI feature flag.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/xfs/xfs_ioctl.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 59eaad774371..97314fcb7732 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -516,6 +516,13 @@ xfs_fileattr_get(
xfs_fill_fsxattr(ip, XFS_DATA_FORK, fa);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ /*
+ * XFS is case-sensitive by default, but can be formatted with
+ * ASCII case-insensitive mode enabled.
+ */
+ fa->case_insensitive = xfs_has_asciici(ip->i_mount);
+ fa->case_preserving = true;
+
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 09/16] cifs: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (7 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 08/16] xfs: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-12 17:46 ` [PATCH v3 10/16] nfs: " Chuck Lever
` (7 subsequent siblings)
16 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Upper layers such as NFSD need a way to query whether a filesystem
handles filenames in a case-sensitive manner. The file_kattr
structure now provides case_insensitive and case_preserving fields
for this purpose, but CIFS does not yet report its case sensitivity
behavior through this interface.
Implement cifs_fileattr_get() to report CIFS/SMB case handling
behavior. CIFS servers (typically Windows or Samba) are usually
case-insensitive but case-preserving, meaning they ignore case
during lookups but store filenames exactly as provided.
The implementation reports case sensitivity based on the nocase
mount option, which reflects whether the client expects the server
to perform case-insensitive comparisons. When nocase is set, the
mount is reported as case-insensitive. The case_preserving field
is always set to true since SMB servers preserve filename case at
rest.
The callback is registered in all three inode_operations
structures (directory, file, and symlink) to ensure consistent
reporting across all inode types.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/smb/client/cifsfs.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index d9664634144d..407afe60ee6c 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -30,6 +30,7 @@
#include <linux/xattr.h>
#include <linux/mm.h>
#include <linux/key-type.h>
+#include <linux/fileattr.h>
#include <uapi/linux/magic.h>
#include <net/ipv6.h>
#include "cifsfs.h"
@@ -1193,6 +1194,21 @@ struct file_system_type smb3_fs_type = {
MODULE_ALIAS_FS("smb3");
MODULE_ALIAS("smb3");
+static int cifs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+
+ /*
+ * CIFS/SMB servers are typically case-insensitive but
+ * case-preserving. The nocase mount option reflects what
+ * the client expects from the server.
+ */
+ fa->case_insensitive = tcon->nocase;
+ fa->case_preserving = true;
+ return 0;
+}
+
const struct inode_operations cifs_dir_inode_ops = {
.create = cifs_create,
.atomic_open = cifs_atomic_open,
@@ -1210,6 +1226,7 @@ const struct inode_operations cifs_dir_inode_ops = {
.listxattr = cifs_listxattr,
.get_acl = cifs_get_acl,
.set_acl = cifs_set_acl,
+ .fileattr_get = cifs_fileattr_get,
};
const struct inode_operations cifs_file_inode_ops = {
@@ -1220,6 +1237,7 @@ const struct inode_operations cifs_file_inode_ops = {
.fiemap = cifs_fiemap,
.get_acl = cifs_get_acl,
.set_acl = cifs_set_acl,
+ .fileattr_get = cifs_fileattr_get,
};
const char *cifs_get_link(struct dentry *dentry, struct inode *inode,
@@ -1254,6 +1272,7 @@ const struct inode_operations cifs_symlink_inode_ops = {
.setattr = cifs_setattr,
.permission = cifs_permission,
.listxattr = cifs_listxattr,
+ .fileattr_get = cifs_fileattr_get,
};
/*
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 10/16] nfs: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (8 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 09/16] cifs: Implement fileattr_get for case sensitivity Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-12 17:46 ` [PATCH v3 11/16] f2fs: Add case sensitivity reporting to fileattr_get Chuck Lever
` (6 subsequent siblings)
16 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
An NFS server re-exporting an NFS mount point needs to report the
case sensitivity behavior of the underlying filesystem to its
clients. Without this, re-export servers cannot accurately convey
case handling semantics, potentially causing client applications to
make incorrect assumptions about filename collisions and lookups.
The NFS client already retrieves case sensitivity information from
servers during mount via PATHCONF (NFSv3) or the
FATTR4_CASE_INSENSITIVE/FATTR4_CASE_PRESERVING attributes (NFSv4).
Expose this information through fileattr_get by reporting the
case_insensitive and case_preserving flags in file_kattr. NFSv2
lacks PATHCONF support, so mounts using that protocol version
default to standard POSIX behavior: case-sensitive and case-
preserving.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/client.c | 9 +++++++--
fs/nfs/inode.c | 18 ++++++++++++++++++
fs/nfs/internal.h | 3 +++
fs/nfs/nfs3proc.c | 2 ++
fs/nfs/nfs3xdr.c | 7 +++++--
fs/nfs/nfs4proc.c | 2 ++
fs/nfs/proc.c | 3 +++
fs/nfs/symlink.c | 3 +++
include/linux/nfs_xdr.h | 2 ++
9 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 2aaea9c98c2c..da437d89e14a 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -935,13 +935,18 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
/* Get some general file system info */
if (server->namelen == 0) {
- struct nfs_pathconf pathinfo;
+ struct nfs_pathconf pathinfo = { };
pathinfo.fattr = fattr;
nfs_fattr_init(fattr);
- if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
+ if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) {
server->namelen = pathinfo.max_namelen;
+ if (pathinfo.case_insensitive)
+ server->caps |= NFS_CAP_CASE_INSENSITIVE;
+ if (pathinfo.case_preserving)
+ server->caps |= NFS_CAP_CASE_PRESERVING;
+ }
}
if (clp->rpc_ops->discover_trunking != NULL &&
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 84049f3cd340..268b254bf0c7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -41,6 +41,7 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/iversion.h>
+#include <linux/fileattr.h>
#include "nfs4_fs.h"
#include "callback.h"
@@ -1100,6 +1101,23 @@ int nfs_getattr(struct mnt_idmap *idmap, const struct path *path,
}
EXPORT_SYMBOL_GPL(nfs_getattr);
+/**
+ * nfs_fileattr_get - Retrieve file attributes
+ * @dentry: object to query
+ * @fa: file attributes to fill in
+ *
+ * Return: 0 on success
+ */
+int nfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ struct inode *inode = d_inode(dentry);
+
+ fa->case_insensitive = nfs_server_capable(inode, NFS_CAP_CASE_INSENSITIVE);
+ fa->case_preserving = nfs_server_capable(inode, NFS_CAP_CASE_PRESERVING);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nfs_fileattr_get);
+
static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
{
refcount_set(&l_ctx->count, 1);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2e596244799f..a843e076aad7 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -453,6 +453,9 @@ extern void nfs_set_cache_invalid(struct inode *inode, unsigned long flags);
extern bool nfs_check_cache_invalid(struct inode *, unsigned long);
extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
+struct file_kattr;
+int nfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
+
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
/* localio.c */
struct nfs_local_dio {
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 1181f9cc6dbd..60344a83f400 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -1048,6 +1048,7 @@ static const struct inode_operations nfs3_dir_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+ .fileattr_get = nfs_fileattr_get,
#ifdef CONFIG_NFS_V3_ACL
.listxattr = nfs3_listxattr,
.get_inode_acl = nfs3_get_acl,
@@ -1059,6 +1060,7 @@ static const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+ .fileattr_get = nfs_fileattr_get,
#ifdef CONFIG_NFS_V3_ACL
.listxattr = nfs3_listxattr,
.get_inode_acl = nfs3_get_acl,
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index e17d72908412..e745e78faab0 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -2276,8 +2276,11 @@ static int decode_pathconf3resok(struct xdr_stream *xdr,
if (unlikely(!p))
return -EIO;
result->max_link = be32_to_cpup(p++);
- result->max_namelen = be32_to_cpup(p);
- /* ignore remaining fields */
+ result->max_namelen = be32_to_cpup(p++);
+ p++; /* ignore no_trunc */
+ p++; /* ignore chown_restricted */
+ result->case_insensitive = be32_to_cpup(p++) != 0;
+ result->case_preserving = be32_to_cpup(p) != 0;
return 0;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ec1ce593dea2..e119c6ff61f0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -11041,6 +11041,7 @@ static const struct inode_operations nfs4_dir_inode_operations = {
.getattr = nfs_getattr,
.setattr = nfs_setattr,
.listxattr = nfs4_listxattr,
+ .fileattr_get = nfs_fileattr_get,
};
static const struct inode_operations nfs4_file_inode_operations = {
@@ -11048,6 +11049,7 @@ static const struct inode_operations nfs4_file_inode_operations = {
.getattr = nfs_getattr,
.setattr = nfs_setattr,
.listxattr = nfs4_listxattr,
+ .fileattr_get = nfs_fileattr_get,
};
static struct nfs_server *nfs4_clone_server(struct nfs_server *source,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 39df80e4ae6f..48f02a80b800 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -597,6 +597,7 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
{
info->max_link = 0;
info->max_namelen = NFS2_MAXNAMLEN;
+ info->case_preserving = true;
return 0;
}
@@ -718,12 +719,14 @@ static const struct inode_operations nfs_dir_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+ .fileattr_get = nfs_fileattr_get,
};
static const struct inode_operations nfs_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+ .fileattr_get = nfs_fileattr_get,
};
const struct nfs_rpc_ops nfs_v2_clientops = {
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 58146e935402..74a072896f8d 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -22,6 +22,8 @@
#include <linux/mm.h>
#include <linux/string.h>
+#include "internal.h"
+
/* Symlink caching in the page cache is even more simplistic
* and straight-forward than readdir caching.
*/
@@ -74,4 +76,5 @@ const struct inode_operations nfs_symlink_inode_operations = {
.get_link = nfs_get_link,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+ .fileattr_get = nfs_fileattr_get,
};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 79fe2dfb470f..5f061a9db2c2 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -182,6 +182,8 @@ struct nfs_pathconf {
struct nfs_fattr *fattr; /* Post-op attributes */
__u32 max_link; /* max # of hard links */
__u32 max_namelen; /* max name length */
+ bool case_insensitive;
+ bool case_preserving;
};
struct nfs4_change_info {
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 11/16] f2fs: Add case sensitivity reporting to fileattr_get
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (9 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 10/16] nfs: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-14 0:50 ` Chao Yu
2026-01-12 17:46 ` [PATCH v3 12/16] vboxsf: Implement fileattr_get for case sensitivity Chuck Lever
` (5 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
NFS and other remote filesystem protocols need to determine
whether a local filesystem performs case-insensitive lookups
so they can provide correct semantics to clients. Without
this information, f2fs exports cannot properly advertise
their filename case behavior.
Report f2fs case sensitivity behavior via the file_kattr
boolean fields. Like ext4, f2fs supports per-directory case
folding via the casefold flag (IS_CASEFOLDED). Files are
always case-preserving.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/f2fs/file.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d7047ca6b98d..e73e6d21d36b 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3439,6 +3439,14 @@ int f2fs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)))
fa->fsx_projid = from_kprojid(&init_user_ns, fi->i_projid);
+ /*
+ * f2fs always preserves case. If this inode is a casefolded
+ * directory, report case-insensitive; otherwise report
+ * case-sensitive (standard POSIX behavior).
+ */
+ fa->case_insensitive = IS_CASEFOLDED(inode);
+ fa->case_preserving = true;
+
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 12/16] vboxsf: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (10 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 11/16] f2fs: Add case sensitivity reporting to fileattr_get Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-12 17:46 ` [PATCH v3 13/16] isofs: " Chuck Lever
` (4 subsequent siblings)
16 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Upper layers such as NFSD need a way to query whether a
filesystem handles filenames in a case-sensitive manner. The
file_kattr structure now provides case_insensitive and
case_preserving fields for this purpose, but vboxsf does not
yet report its case sensitivity behavior through this interface.
Implement vboxsf_fileattr_get() to report the case handling
behavior of VirtualBox shared folders. The case sensitivity
property is queried from the VirtualBox host service at mount
time and cached in struct vboxsf_sbi. The host determines case
sensitivity based on the underlying host filesystem (for
example, Windows NTFS is case-insensitive while Linux ext4 is
case-sensitive).
VirtualBox shared folders always preserve filename case exactly
as provided by the guest. The host interface does not expose a
case_preserving property, so this is hardcoded to true.
The callback is registered in all three inode_operations
structures (directory, file, and symlink) to ensure consistent
reporting across all inode types.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/vboxsf/dir.c | 1 +
fs/vboxsf/file.c | 6 ++++--
fs/vboxsf/super.c | 4 ++++
fs/vboxsf/utils.c | 31 +++++++++++++++++++++++++++++++
fs/vboxsf/vfsmod.h | 6 ++++++
5 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/fs/vboxsf/dir.c b/fs/vboxsf/dir.c
index 42bedc4ec7af..c5bd3271aa96 100644
--- a/fs/vboxsf/dir.c
+++ b/fs/vboxsf/dir.c
@@ -477,4 +477,5 @@ const struct inode_operations vboxsf_dir_iops = {
.symlink = vboxsf_dir_symlink,
.getattr = vboxsf_getattr,
.setattr = vboxsf_setattr,
+ .fileattr_get = vboxsf_fileattr_get,
};
diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
index 4bebd947314a..06308e38a70d 100644
--- a/fs/vboxsf/file.c
+++ b/fs/vboxsf/file.c
@@ -223,7 +223,8 @@ const struct file_operations vboxsf_reg_fops = {
const struct inode_operations vboxsf_reg_iops = {
.getattr = vboxsf_getattr,
- .setattr = vboxsf_setattr
+ .setattr = vboxsf_setattr,
+ .fileattr_get = vboxsf_fileattr_get,
};
static int vboxsf_read_folio(struct file *file, struct folio *folio)
@@ -390,5 +391,6 @@ static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode,
}
const struct inode_operations vboxsf_lnk_iops = {
- .get_link = vboxsf_get_link
+ .get_link = vboxsf_get_link,
+ .fileattr_get = vboxsf_fileattr_get,
};
diff --git a/fs/vboxsf/super.c b/fs/vboxsf/super.c
index 241647b060ee..fcabeca2a339 100644
--- a/fs/vboxsf/super.c
+++ b/fs/vboxsf/super.c
@@ -185,6 +185,10 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
if (err)
goto fail_unmap;
+ err = vboxsf_query_case_sensitive(sbi);
+ if (err)
+ goto fail_unmap;
+
sb->s_magic = VBOXSF_SUPER_MAGIC;
sb->s_blocksize = 1024;
sb->s_maxbytes = MAX_LFS_FILESIZE;
diff --git a/fs/vboxsf/utils.c b/fs/vboxsf/utils.c
index 9515bbf0b54c..0908fc071577 100644
--- a/fs/vboxsf/utils.c
+++ b/fs/vboxsf/utils.c
@@ -11,6 +11,7 @@
#include <linux/sizes.h>
#include <linux/pagemap.h>
#include <linux/vfs.h>
+#include <linux/fileattr.h>
#include "vfsmod.h"
struct inode *vboxsf_new_inode(struct super_block *sb)
@@ -567,3 +568,33 @@ int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
return err;
}
+
+int vboxsf_query_case_sensitive(struct vboxsf_sbi *sbi)
+{
+ struct shfl_volinfo volinfo;
+ u32 buf_len;
+ int err;
+
+ buf_len = sizeof(volinfo);
+ err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
+ &buf_len, &volinfo);
+ if (err)
+ return err;
+
+ sbi->case_insensitive = !volinfo.properties.case_sensitive;
+ return 0;
+}
+
+int vboxsf_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
+
+ fa->case_insensitive = sbi->case_insensitive;
+ /*
+ * VirtualBox shared folders always preserve filename case
+ * exactly as provided by the guest. The host interface does
+ * not expose a case_preserving property.
+ */
+ fa->case_preserving = true;
+ return 0;
+}
diff --git a/fs/vboxsf/vfsmod.h b/fs/vboxsf/vfsmod.h
index 05973eb89d52..b61afd0ce842 100644
--- a/fs/vboxsf/vfsmod.h
+++ b/fs/vboxsf/vfsmod.h
@@ -47,6 +47,7 @@ struct vboxsf_sbi {
u32 next_generation;
u32 root;
int bdi_id;
+ bool case_insensitive;
};
/* per-inode information */
@@ -111,6 +112,11 @@ void vboxsf_dir_info_free(struct vboxsf_dir_info *p);
int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
u64 handle);
+int vboxsf_query_case_sensitive(struct vboxsf_sbi *sbi);
+
+struct file_kattr;
+int vboxsf_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
+
/* from vboxsf_wrappers.c */
int vboxsf_connect(void);
void vboxsf_disconnect(void);
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 13/16] isofs: Implement fileattr_get for case sensitivity
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (11 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 12/16] vboxsf: Implement fileattr_get for case sensitivity Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-13 11:50 ` Jan Kara
2026-01-12 17:46 ` [PATCH v3 14/16] nfsd: Report export case-folding via NFSv3 PATHCONF Chuck Lever
` (3 subsequent siblings)
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
Upper layers such as NFSD need a way to query whether a
filesystem handles filenames in a case-sensitive manner so
they can provide correct semantics to remote clients. Without
this information, NFS exports of ISO 9660 filesystems cannot
properly advertise their filename case behavior.
Implement isofs_fileattr_get() to report ISO 9660 case
handling behavior. The 'check=r' (relaxed) mount option
enables case-insensitive lookups, and this setting determines
the value reported through the file_kattr structure. By
default, Joliet extensions operate in relaxed mode while plain
ISO 9660 uses strict (case-sensitive) mode. All ISO 9660
variants are case-preserving, meaning filenames are stored
exactly as they appear on the disc.
The callback is registered only on isofs_dir_inode_operations
because isofs has no custom inode_operations for regular
files, and symlinks use the generic page_symlink_inode_operations.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/isofs/dir.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 09df40b612fb..717cdf726e83 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -12,6 +12,7 @@
* isofs directory handling functions
*/
#include <linux/gfp.h>
+#include <linux/fileattr.h>
#include "isofs.h"
int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
@@ -266,6 +267,15 @@ static int isofs_readdir(struct file *file, struct dir_context *ctx)
return result;
}
+static int isofs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
+{
+ struct isofs_sb_info *sbi = ISOFS_SB(dentry->d_sb);
+
+ fa->case_insensitive = sbi->s_check == 'r';
+ fa->case_preserving = true;
+ return 0;
+}
+
const struct file_operations isofs_dir_operations =
{
.llseek = generic_file_llseek,
@@ -279,6 +289,7 @@ const struct file_operations isofs_dir_operations =
const struct inode_operations isofs_dir_inode_operations =
{
.lookup = isofs_lookup,
+ .fileattr_get = isofs_fileattr_get,
};
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 14/16] nfsd: Report export case-folding via NFSv3 PATHCONF
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (12 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 13/16] isofs: " Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-12 17:46 ` [PATCH v3 15/16] nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING Chuck Lever
` (2 subsequent siblings)
16 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
The hard-coded MSDOS_SUPER_MAGIC check in nfsd3_proc_pathconf()
only recognizes FAT filesystems as case-insensitive. Modern
filesystems like F2FS, exFAT, and CIFS support case-insensitive
directories, but NFSv3 clients cannot discover this capability.
Query the export's actual case behavior through ->fileattr_get
instead. This allows NFSv3 clients to correctly handle case
sensitivity for any filesystem that implements the fileattr
interface. Filesystems without ->fileattr_get continue to report
the default POSIX behavior (case-sensitive, case-preserving).
This change assumes the ("fat: Implement fileattr_get for case
sensitivity") has been applied, which ensures FAT filesystems
report their case behavior correctly via the fileattr interface.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfs3proc.c | 18 ++++++++++--------
fs/nfsd/vfs.c | 25 +++++++++++++++++++++++++
fs/nfsd/vfs.h | 2 ++
3 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 42adc5461db0..9be0aca01de0 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -717,17 +717,19 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp)
if (resp->status == nfs_ok) {
struct super_block *sb = argp->fh.fh_dentry->d_sb;
+ bool case_insensitive, case_preserving;
- /* Note that we don't care for remote fs's here */
- switch (sb->s_magic) {
- case EXT2_SUPER_MAGIC:
+ if (sb->s_magic == EXT2_SUPER_MAGIC) {
resp->p_link_max = EXT2_LINK_MAX;
resp->p_name_max = EXT2_NAME_LEN;
- break;
- case MSDOS_SUPER_MAGIC:
- resp->p_case_insensitive = 1;
- resp->p_case_preserving = 0;
- break;
+ }
+
+ resp->status = nfsd_get_case_info(&argp->fh,
+ &case_insensitive,
+ &case_preserving);
+ if (resp->status == nfs_ok) {
+ resp->p_case_insensitive = case_insensitive;
+ resp->p_case_preserving = case_preserving;
}
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 168d3ccc8155..f65985813fbf 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -32,6 +32,7 @@
#include <linux/writeback.h>
#include <linux/security.h>
#include <linux/sunrpc/xdr.h>
+#include <linux/fileattr.h>
#include "xdr3.h"
@@ -2871,3 +2872,27 @@ nfsd_permission(struct svc_cred *cred, struct svc_export *exp,
return err? nfserrno(err) : 0;
}
+
+/**
+ * nfsd_get_case_info - get case sensitivity info for a file handle
+ * @fhp: file handle that has already been verified
+ * @case_insensitive: output, true if the filesystem is case-insensitive
+ * @case_preserving: output, true if the filesystem preserves case
+ *
+ * Returns nfs_ok on success, or an nfserr on failure.
+ */
+__be32
+nfsd_get_case_info(struct svc_fh *fhp, bool *case_insensitive,
+ bool *case_preserving)
+{
+ struct file_kattr fa = {};
+ int err;
+
+ err = vfs_fileattr_get(fhp->fh_dentry, &fa);
+ if (err && err != -ENOIOCTLCMD)
+ return nfserrno(err);
+
+ *case_insensitive = fa.case_insensitive;
+ *case_preserving = fa.case_preserving;
+ return nfs_ok;
+}
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index e192dca4a679..1ff62eecec09 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -155,6 +155,8 @@ __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
loff_t *, struct readdir_cd *, nfsd_filldir_t);
__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct kstatfs *, int access);
+__be32 nfsd_get_case_info(struct svc_fh *fhp, bool *case_insensitive,
+ bool *case_preserving);
__be32 nfsd_permission(struct svc_cred *cred, struct svc_export *exp,
struct dentry *dentry, int acc);
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 15/16] nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (13 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 14/16] nfsd: Report export case-folding via NFSv3 PATHCONF Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-12 17:46 ` [PATCH v3 16/16] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION Chuck Lever
2026-01-13 9:04 ` [PATCH v3 00/16] Exposing case folding behavior Christian Brauner
16 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
NFSD currently provides NFSv4 clients with hard-coded responses
indicating all exported filesystems are case-sensitive and
case-preserving. This is incorrect for case-insensitive filesystems
and ext4 directories with casefold enabled.
Query the underlying filesystem's actual case sensitivity via
nfsd_get_case_info() and return accurate values to clients. This
supports per-directory settings for filesystems that allow mixing
case-sensitive and case-insensitive directories within an export.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfs4xdr.c | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 51ef97c25456..167bede81273 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2933,6 +2933,8 @@ struct nfsd4_fattr_args {
u32 rdattr_err;
bool contextsupport;
bool ignore_crossmnt;
+ bool case_insensitive;
+ bool case_preserving;
};
typedef __be32(*nfsd4_enc_attr)(struct xdr_stream *xdr,
@@ -3131,6 +3133,18 @@ static __be32 nfsd4_encode_fattr4_acl(struct xdr_stream *xdr,
return nfs_ok;
}
+static __be32 nfsd4_encode_fattr4_case_insensitive(struct xdr_stream *xdr,
+ const struct nfsd4_fattr_args *args)
+{
+ return nfsd4_encode_bool(xdr, args->case_insensitive);
+}
+
+static __be32 nfsd4_encode_fattr4_case_preserving(struct xdr_stream *xdr,
+ const struct nfsd4_fattr_args *args)
+{
+ return nfsd4_encode_bool(xdr, args->case_preserving);
+}
+
static __be32 nfsd4_encode_fattr4_filehandle(struct xdr_stream *xdr,
const struct nfsd4_fattr_args *args)
{
@@ -3487,8 +3501,8 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
[FATTR4_ACLSUPPORT] = nfsd4_encode_fattr4_aclsupport,
[FATTR4_ARCHIVE] = nfsd4_encode_fattr4__noop,
[FATTR4_CANSETTIME] = nfsd4_encode_fattr4__true,
- [FATTR4_CASE_INSENSITIVE] = nfsd4_encode_fattr4__false,
- [FATTR4_CASE_PRESERVING] = nfsd4_encode_fattr4__true,
+ [FATTR4_CASE_INSENSITIVE] = nfsd4_encode_fattr4_case_insensitive,
+ [FATTR4_CASE_PRESERVING] = nfsd4_encode_fattr4_case_preserving,
[FATTR4_CHOWN_RESTRICTED] = nfsd4_encode_fattr4__true,
[FATTR4_FILEHANDLE] = nfsd4_encode_fattr4_filehandle,
[FATTR4_FILEID] = nfsd4_encode_fattr4_fileid,
@@ -3674,8 +3688,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
if (err)
goto out_nfserr;
}
- if ((attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
- !fhp) {
+ if ((attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID |
+ FATTR4_WORD0_CASE_INSENSITIVE |
+ FATTR4_WORD0_CASE_PRESERVING)) && !fhp) {
tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
status = nfserr_jukebox;
if (!tempfh)
@@ -3687,6 +3702,13 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
args.fhp = tempfh;
} else
args.fhp = fhp;
+ if (attrmask[0] & (FATTR4_WORD0_CASE_INSENSITIVE |
+ FATTR4_WORD0_CASE_PRESERVING)) {
+ status = nfsd_get_case_info(args.fhp, &args.case_insensitive,
+ &args.case_preserving);
+ if (status != nfs_ok)
+ goto out;
+ }
if (attrmask[0] & FATTR4_WORD0_ACL) {
err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
--
2.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 16/16] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (14 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 15/16] nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING Chuck Lever
@ 2026-01-12 17:46 ` Chuck Lever
2026-01-14 0:46 ` Namjae Jeon
2026-01-13 9:04 ` [PATCH v3 00/16] Exposing case folding behavior Christian Brauner
16 siblings, 1 reply; 30+ messages in thread
From: Chuck Lever @ 2026-01-12 17:46 UTC (permalink / raw)
To: vira, Christian Brauner, Jan Kara
Cc: linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
From: Chuck Lever <chuck.lever@oracle.com>
ksmbd hard-codes FILE_CASE_SENSITIVE_SEARCH and
FILE_CASE_PRESERVED_NAMES in FS_ATTRIBUTE_INFORMATION responses,
incorrectly indicating all exports are case-sensitive. This breaks
clients accessing case-insensitive filesystems like exFAT or
ext4/f2fs directories with casefold enabled.
Query actual case behavior via vfs_fileattr_get() and report accurate
attributes to SMB clients. 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.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
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 2fcd0d4d1fb0..2db189fef4da 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -13,6 +13,7 @@
#include <linux/falloc.h>
#include <linux/mount.h>
#include <linux/filelock.h>
+#include <linux/fileattr.h>
#include "glob.h"
#include "smbfsctl.h"
@@ -5486,16 +5487,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);
+ if (err && err != -ENOIOCTLCMD) {
+ path_put(&path);
+ return err;
+ }
+ if (err == -ENOIOCTLCMD) {
+ /* Default POSIX: case-sensitive and case-preserving */
+ fa.case_insensitive = false;
+ fa.case_preserving = true;
+ }
+ if (!fa.case_insensitive)
+ attrs |= FILE_CASE_SENSITIVE_SEARCH;
+ if (fa.case_preserving)
+ 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.52.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v3 00/16] Exposing case folding behavior
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
` (15 preceding siblings ...)
2026-01-12 17:46 ` [PATCH v3 16/16] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION Chuck Lever
@ 2026-01-13 9:04 ` Christian Brauner
2026-01-13 13:58 ` Chuck Lever
16 siblings, 1 reply; 30+ messages in thread
From: Christian Brauner @ 2026-01-13 9:04 UTC (permalink / raw)
To: Chuck Lever
Cc: vira, Jan Kara, linux-fsdevel, linux-ext4, linux-xfs, linux-cifs,
linux-nfs, linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo,
yuezhang.mo, almaz.alexandrovich, slava, glaubitz, frank.li,
tytso, adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
On Mon, Jan 12, 2026 at 12:46:13PM -0500, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Following on from
>
> https://lore.kernel.org/linux-nfs/20251021-zypressen-bazillus-545a44af57fd@brauner/T/#m0ba197d75b7921d994cf284f3cef3a62abb11aaa
>
> I'm attempting to implement enough support in the Linux VFS to
> enable file services like NFSD and ksmbd (and user space
> equivalents) to provide the actual status of case folding support
> in local file systems. The default behavior for local file systems
> not explicitly supported in this series is to reflect the usual
> POSIX behaviors:
>
> case-insensitive = false
> case-preserving = true
>
> The case-insensitivity and case-preserving booleans can be consumed
> immediately by NFSD. These two booleans have been part of the NFSv3
> and NFSv4 protocols for decades, in order to support NFS clients on
> non-POSIX systems.
>
> Support for user space file servers is why this series exposes case
> folding information via a user-space API. I don't know of any other
> category of user-space application that requires access to case
> folding info.
This all looks good to me.
Just one question: This reads like you are exposing the new file attr
bits via userspace but I can only see changes to the kernel internal
headers not the uapi headers. So are you intentionally not exposing this
as a new uapi extension to file attr or is this an accident?
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 13/16] isofs: Implement fileattr_get for case sensitivity
2026-01-12 17:46 ` [PATCH v3 13/16] isofs: " Chuck Lever
@ 2026-01-13 11:50 ` Jan Kara
0 siblings, 0 replies; 30+ messages in thread
From: Jan Kara @ 2026-01-13 11:50 UTC (permalink / raw)
To: Chuck Lever
Cc: vira, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi,
linkinjeon, sj1557.seo, yuezhang.mo, almaz.alexandrovich, slava,
glaubitz, frank.li, tytso, adilger.kernel, cem, sfrench, pc,
ronniesahlberg, sprasad, trondmy, anna, jaegeuk, chao, hansg,
senozhatsky, Chuck Lever
On Mon 12-01-26 12:46:26, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Upper layers such as NFSD need a way to query whether a
> filesystem handles filenames in a case-sensitive manner so
> they can provide correct semantics to remote clients. Without
> this information, NFS exports of ISO 9660 filesystems cannot
> properly advertise their filename case behavior.
>
> Implement isofs_fileattr_get() to report ISO 9660 case
> handling behavior. The 'check=r' (relaxed) mount option
> enables case-insensitive lookups, and this setting determines
> the value reported through the file_kattr structure. By
> default, Joliet extensions operate in relaxed mode while plain
> ISO 9660 uses strict (case-sensitive) mode. All ISO 9660
> variants are case-preserving, meaning filenames are stored
> exactly as they appear on the disc.
>
> The callback is registered only on isofs_dir_inode_operations
> because isofs has no custom inode_operations for regular
> files, and symlinks use the generic page_symlink_inode_operations.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/isofs/dir.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
> index 09df40b612fb..717cdf726e83 100644
> --- a/fs/isofs/dir.c
> +++ b/fs/isofs/dir.c
> @@ -12,6 +12,7 @@
> * isofs directory handling functions
> */
> #include <linux/gfp.h>
> +#include <linux/fileattr.h>
> #include "isofs.h"
>
> int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
> @@ -266,6 +267,15 @@ static int isofs_readdir(struct file *file, struct dir_context *ctx)
> return result;
> }
>
> +static int isofs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
> +{
> + struct isofs_sb_info *sbi = ISOFS_SB(dentry->d_sb);
> +
> + fa->case_insensitive = sbi->s_check == 'r';
> + fa->case_preserving = true;
> + return 0;
> +}
> +
> const struct file_operations isofs_dir_operations =
> {
> .llseek = generic_file_llseek,
> @@ -279,6 +289,7 @@ const struct file_operations isofs_dir_operations =
> const struct inode_operations isofs_dir_inode_operations =
> {
> .lookup = isofs_lookup,
> + .fileattr_get = isofs_fileattr_get,
> };
>
>
> --
> 2.52.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 07/16] ext4: Report case sensitivity in fileattr_get
2026-01-12 17:46 ` [PATCH v3 07/16] ext4: " Chuck Lever
@ 2026-01-13 11:50 ` Jan Kara
0 siblings, 0 replies; 30+ messages in thread
From: Jan Kara @ 2026-01-13 11:50 UTC (permalink / raw)
To: Chuck Lever
Cc: vira, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi,
linkinjeon, sj1557.seo, yuezhang.mo, almaz.alexandrovich, slava,
glaubitz, frank.li, tytso, adilger.kernel, cem, sfrench, pc,
ronniesahlberg, sprasad, trondmy, anna, jaegeuk, chao, hansg,
senozhatsky, Chuck Lever
On Mon 12-01-26 12:46:20, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Report ext4's case sensitivity behavior via file_kattr boolean
> fields. ext4 always preserves case at rest.
>
> Case sensitivity is a per-directory setting in ext4. If the queried
> inode is a casefolded directory, report case-insensitive; otherwise
> report case-sensitive (standard POSIX behavior).
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/ioctl.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index 7ce0fc40aec2..653035017c7f 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -996,6 +996,14 @@ int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
> if (ext4_has_feature_project(inode->i_sb))
> fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
>
> + /*
> + * ext4 always preserves case. If this inode is a casefolded
> + * directory, report case-insensitive; otherwise report
> + * case-sensitive (standard POSIX behavior).
> + */
> + fa->case_insensitive = IS_CASEFOLDED(inode);
> + fa->case_preserving = true;
> +
> return 0;
> }
>
> --
> 2.52.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 00/16] Exposing case folding behavior
2026-01-13 9:04 ` [PATCH v3 00/16] Exposing case folding behavior Christian Brauner
@ 2026-01-13 13:58 ` Chuck Lever
0 siblings, 0 replies; 30+ messages in thread
From: Chuck Lever @ 2026-01-13 13:58 UTC (permalink / raw)
To: Christian Brauner
Cc: vira, Jan Kara, linux-fsdevel, linux-ext4, linux-xfs, linux-cifs,
linux-nfs, linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo,
yuezhang.mo, almaz.alexandrovich, slava, glaubitz, frank.li,
tytso, adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
On 1/13/26 4:04 AM, Christian Brauner wrote:
> On Mon, Jan 12, 2026 at 12:46:13PM -0500, Chuck Lever wrote:
>> From: Chuck Lever <chuck.lever@oracle.com>
>>
>> Following on from
>>
>> https://lore.kernel.org/linux-nfs/20251021-zypressen-bazillus-545a44af57fd@brauner/T/#m0ba197d75b7921d994cf284f3cef3a62abb11aaa
>>
>> I'm attempting to implement enough support in the Linux VFS to
>> enable file services like NFSD and ksmbd (and user space
>> equivalents) to provide the actual status of case folding support
>> in local file systems. The default behavior for local file systems
>> not explicitly supported in this series is to reflect the usual
>> POSIX behaviors:
>>
>> case-insensitive = false
>> case-preserving = true
>>
>> The case-insensitivity and case-preserving booleans can be consumed
>> immediately by NFSD. These two booleans have been part of the NFSv3
>> and NFSv4 protocols for decades, in order to support NFS clients on
>> non-POSIX systems.
>>
>> Support for user space file servers is why this series exposes case
>> folding information via a user-space API. I don't know of any other
>> category of user-space application that requires access to case
>> folding info.
>
> This all looks good to me.
> Just one question: This reads like you are exposing the new file attr
> bits via userspace but I can only see changes to the kernel internal
> headers not the uapi headers. So are you intentionally not exposing this
> as a new uapi extension to file attr or is this an accident?
The intention is to expose the new bits to user space. IIRC those got
removed from uapi headers when I converted from using statx. I can fix
that up and post a v4.
--
Chuck Lever
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr
2026-01-12 17:46 ` [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr Chuck Lever
@ 2026-01-13 15:21 ` Christoph Hellwig
0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2026-01-13 15:21 UTC (permalink / raw)
To: Chuck Lever
Cc: vira, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi,
linkinjeon, sj1557.seo, yuezhang.mo, almaz.alexandrovich, slava,
glaubitz, frank.li, tytso, adilger.kernel, cem, sfrench, pc,
ronniesahlberg, sprasad, trondmy, anna, jaegeuk, chao, hansg,
senozhatsky, Chuck Lever
> + /* case sensitivity behavior: */
> + bool case_insensitive:1;
> + bool case_preserving:1;
Given that not case preserving is by far the exception, maybe have
a flag for that instead?
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 02/16] fat: Implement fileattr_get for case sensitivity
2026-01-12 17:46 ` [PATCH v3 02/16] fat: Implement fileattr_get for case sensitivity Chuck Lever
@ 2026-01-13 15:23 ` Christoph Hellwig
0 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2026-01-13 15:23 UTC (permalink / raw)
To: Chuck Lever
Cc: vira, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi,
linkinjeon, sj1557.seo, yuezhang.mo, almaz.alexandrovich, slava,
glaubitz, frank.li, tytso, adilger.kernel, cem, sfrench, pc,
ronniesahlberg, sprasad, trondmy, anna, jaegeuk, chao, hansg,
senozhatsky, Chuck Lever
> +extern int fat_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
No need for "extern" for function prototypes.
> +int fat_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
> +{
> + struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
> +
> + /*
> + * FAT filesystems do not preserve case: stored names are
Is that actually true? It's been a while since I deal with them,
but IIRC at least vfat is case preserving.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/16] xfs: Report case sensitivity in fileattr_get
2026-01-12 17:46 ` [PATCH v3 08/16] xfs: " Chuck Lever
@ 2026-01-13 16:02 ` Darrick J. Wong
2026-01-13 16:43 ` Neal Gompa
0 siblings, 1 reply; 30+ messages in thread
From: Darrick J. Wong @ 2026-01-13 16:02 UTC (permalink / raw)
To: Chuck Lever
Cc: vira, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi,
linkinjeon, sj1557.seo, yuezhang.mo, almaz.alexandrovich, slava,
glaubitz, frank.li, tytso, adilger.kernel, cem, sfrench, pc,
ronniesahlberg, sprasad, trondmy, anna, jaegeuk, chao, hansg,
senozhatsky, Chuck Lever, Neal Gompa
On Mon, Jan 12, 2026 at 12:46:21PM -0500, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Upper layers such as NFSD need to query whether a filesystem is
> case-sensitive. Populate the case_insensitive and case_preserving
> fields in xfs_fileattr_get(). XFS always preserves case. XFS is
> case-sensitive by default, but supports ASCII case-insensitive
> lookups when formatted with the ASCIICI feature flag.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Well as a pure binary statement of xfs' capabilities, this is correct so:
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
[add ngompa]
But the next obvious question I would have as a userspace programmer is
"case insensitive how, exactly?", which was the topic of the previous
revision. Somewhere out there there's a program / emulation layer that
will want to know the exact transformation when doing a non-memcmp
lookup. Probably Winderz casefolding has behaved differently every
release since the start of NTFS, etc.
I don't know how to solve that, other than the fs compiles its
case-flattening code into a bpf program and exports that where someone
can read() it and run/analyze/reverse engineer it. But ugh, Linus is
right that this area is a mess. :/
--D
> ---
> fs/xfs/xfs_ioctl.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 59eaad774371..97314fcb7732 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -516,6 +516,13 @@ xfs_fileattr_get(
> xfs_fill_fsxattr(ip, XFS_DATA_FORK, fa);
> xfs_iunlock(ip, XFS_ILOCK_SHARED);
>
> + /*
> + * XFS is case-sensitive by default, but can be formatted with
> + * ASCII case-insensitive mode enabled.
> + */
> + fa->case_insensitive = xfs_has_asciici(ip->i_mount);
> + fa->case_preserving = true;
> +
> return 0;
> }
>
> --
> 2.52.0
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/16] xfs: Report case sensitivity in fileattr_get
2026-01-13 16:02 ` Darrick J. Wong
@ 2026-01-13 16:43 ` Neal Gompa
0 siblings, 0 replies; 30+ messages in thread
From: Neal Gompa @ 2026-01-13 16:43 UTC (permalink / raw)
To: Darrick J. Wong
Cc: Chuck Lever, vira, Christian Brauner, Jan Kara, linux-fsdevel,
linux-ext4, linux-xfs, linux-cifs, linux-nfs, linux-f2fs-devel,
hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
On Tue, Jan 13, 2026 at 11:02 AM Darrick J. Wong <djwong@kernel.org> wrote:
>
> On Mon, Jan 12, 2026 at 12:46:21PM -0500, Chuck Lever wrote:
> > From: Chuck Lever <chuck.lever@oracle.com>
> >
> > Upper layers such as NFSD need to query whether a filesystem is
> > case-sensitive. Populate the case_insensitive and case_preserving
> > fields in xfs_fileattr_get(). XFS always preserves case. XFS is
> > case-sensitive by default, but supports ASCII case-insensitive
> > lookups when formatted with the ASCIICI feature flag.
> >
> > Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>
> Well as a pure binary statement of xfs' capabilities, this is correct so:
> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
>
> [add ngompa]
>
> But the next obvious question I would have as a userspace programmer is
> "case insensitive how, exactly?", which was the topic of the previous
> revision. Somewhere out there there's a program / emulation layer that
> will want to know the exact transformation when doing a non-memcmp
> lookup. Probably Winderz casefolding has behaved differently every
> release since the start of NTFS, etc.
>
NTFS itself is case preserving and has a namespace for Win32k entries
(case-insensitive) and SFU/SUA/LXSS entries (case-sensitive). I'm not
entirely certain of the nature of *how* those entries are managed, but
I *believe* it's from the personalities themselves.
> I don't know how to solve that, other than the fs compiles its
> case-flattening code into a bpf program and exports that where someone
> can read() it and run/analyze/reverse engineer it. But ugh, Linus is
> right that this area is a mess. :/
>
The biggie is that it has to be NLS aware. That's where it gets
complicated since there are different case rules for different
languages.
--
真実はいつも一つ!/ Always, there's only one truth!
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 05/16] hfs: Implement fileattr_get for case sensitivity
2026-01-12 17:46 ` [PATCH v3 05/16] hfs: " Chuck Lever
@ 2026-01-13 17:35 ` Viacheslav Dubeyko
0 siblings, 0 replies; 30+ messages in thread
From: Viacheslav Dubeyko @ 2026-01-13 17:35 UTC (permalink / raw)
To: cel@kernel.org, jack@suse.cz, brauner@kernel.org,
vira@web.codeaurora.org
Cc: glaubitz@physik.fu-berlin.de, chuck.lever@oracle.com,
chao@kernel.org, linux-xfs@vger.kernel.org, linkinjeon@kernel.org,
linux-cifs@vger.kernel.org, pc@manguebit.org,
yuezhang.mo@sony.com, almaz.alexandrovich@paragon-software.com,
hirofumi@mail.parknet.co.jp, slava@dubeyko.com, anna@kernel.org,
linux-f2fs-devel@lists.sourceforge.net, linux-nfs@vger.kernel.org,
tytso@mit.edu, linux-ext4@vger.kernel.org, sj1557.seo@samsung.com,
trondmy@kernel.org, cem@kernel.org, ronniesahlberg@gmail.com,
jaegeuk@kernel.org, linux-fsdevel@vger.kernel.org,
adilger.kernel@dilger.ca, sfrench@samba.org, frank.li@vivo.com,
sprasad@microsoft.com, hansg@kernel.org, senozhatsky@chromium.org
On Mon, 2026-01-12 at 12:46 -0500, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Report HFS case sensitivity behavior via the file_kattr boolean
> fields. HFS is always case-insensitive (using Mac OS Roman case
> folding) and always preserves case at rest.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
> fs/hfs/dir.c | 1 +
> fs/hfs/hfs_fs.h | 2 ++
> fs/hfs/inode.c | 13 +++++++++++++
> 3 files changed, 16 insertions(+)
>
> diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
> index 86a6b317b474..552156896105 100644
> --- a/fs/hfs/dir.c
> +++ b/fs/hfs/dir.c
> @@ -321,4 +321,5 @@ const struct inode_operations hfs_dir_inode_operations = {
> .rmdir = hfs_remove,
> .rename = hfs_rename,
> .setattr = hfs_inode_setattr,
> + .fileattr_get = hfs_fileattr_get,
> };
> diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
> index e94dbc04a1e4..a25cdda8ab34 100644
> --- a/fs/hfs/hfs_fs.h
> +++ b/fs/hfs/hfs_fs.h
> @@ -177,6 +177,8 @@ extern int hfs_get_block(struct inode *inode, sector_t block,
> extern const struct address_space_operations hfs_aops;
> extern const struct address_space_operations hfs_btree_aops;
>
> +struct file_kattr;
> +int hfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
> int hfs_write_begin(const struct kiocb *iocb, struct address_space *mapping,
> loff_t pos, unsigned int len, struct folio **foliop,
> void **fsdata);
> diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
> index 524db1389737..06429decc1d8 100644
> --- a/fs/hfs/inode.c
> +++ b/fs/hfs/inode.c
> @@ -18,6 +18,7 @@
> #include <linux/uio.h>
> #include <linux/xattr.h>
> #include <linux/blkdev.h>
> +#include <linux/fileattr.h>
>
> #include "hfs_fs.h"
> #include "btree.h"
> @@ -698,6 +699,17 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
> return ret;
> }
>
> +int hfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
> +{
> + /*
> + * HFS is always case-insensitive (using Mac OS Roman case
> + * folding) and always preserves case at rest.
> + */
> + fa->case_insensitive = true;
> + fa->case_preserving = true;
> + return 0;
> +}
> +
> static const struct file_operations hfs_file_operations = {
> .llseek = generic_file_llseek,
> .read_iter = generic_file_read_iter,
> @@ -714,4 +726,5 @@ static const struct inode_operations hfs_file_inode_operations = {
> .lookup = hfs_file_lookup,
> .setattr = hfs_inode_setattr,
> .listxattr = generic_listxattr,
> + .fileattr_get = hfs_fileattr_get,
> };
Looks good.
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Thanks,
Slava.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 06/16] hfsplus: Report case sensitivity in fileattr_get
2026-01-12 17:46 ` [PATCH v3 06/16] hfsplus: Report case sensitivity in fileattr_get Chuck Lever
@ 2026-01-13 17:36 ` Viacheslav Dubeyko
0 siblings, 0 replies; 30+ messages in thread
From: Viacheslav Dubeyko @ 2026-01-13 17:36 UTC (permalink / raw)
To: cel@kernel.org, jack@suse.cz, brauner@kernel.org,
vira@web.codeaurora.org
Cc: glaubitz@physik.fu-berlin.de, chuck.lever@oracle.com,
chao@kernel.org, linux-xfs@vger.kernel.org, linkinjeon@kernel.org,
linux-cifs@vger.kernel.org, pc@manguebit.org,
yuezhang.mo@sony.com, almaz.alexandrovich@paragon-software.com,
hirofumi@mail.parknet.co.jp, slava@dubeyko.com, anna@kernel.org,
linux-f2fs-devel@lists.sourceforge.net, linux-nfs@vger.kernel.org,
tytso@mit.edu, linux-ext4@vger.kernel.org, sj1557.seo@samsung.com,
trondmy@kernel.org, cem@kernel.org, ronniesahlberg@gmail.com,
jaegeuk@kernel.org, linux-fsdevel@vger.kernel.org,
adilger.kernel@dilger.ca, sfrench@samba.org, frank.li@vivo.com,
sprasad@microsoft.com, hansg@kernel.org, senozhatsky@chromium.org
On Mon, 2026-01-12 at 12:46 -0500, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Add case sensitivity reporting to the existing hfsplus_fileattr_get()
> function. HFS+ always preserves case at rest.
>
> Case sensitivity depends on how the volume was formatted: HFSX
> volumes may be either case-sensitive or case-insensitive, indicated
> by the HFSPLUS_SB_CASEFOLD superblock flag.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
> fs/hfsplus/inode.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
> index 7ae6745ca7ae..0ce9561c0f18 100644
> --- a/fs/hfsplus/inode.c
> +++ b/fs/hfsplus/inode.c
> @@ -694,6 +694,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
> {
> struct inode *inode = d_inode(dentry);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> + struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
> unsigned int flags = 0;
>
> if (inode->i_flags & S_IMMUTABLE)
> @@ -705,6 +706,14 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
>
> fileattr_fill_flags(fa, flags);
>
> + /*
> + * HFS+ always preserves case. Case sensitivity depends on how
> + * the filesystem was formatted: HFSX volumes may be either
> + * case-sensitive or case-insensitive.
> + */
> + fa->case_insensitive = test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags);
> + fa->case_preserving = true;
> +
> return 0;
> }
>
Looks good.
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Thanks,
Slava.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 03/16] exfat: Implement fileattr_get for case sensitivity
2026-01-12 17:46 ` [PATCH v3 03/16] exfat: " Chuck Lever
@ 2026-01-14 0:45 ` Namjae Jeon
0 siblings, 0 replies; 30+ messages in thread
From: Namjae Jeon @ 2026-01-14 0:45 UTC (permalink / raw)
To: Chuck Lever
Cc: Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4, linux-xfs,
linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi, sj1557.seo,
yuezhang.mo, almaz.alexandrovich, slava, glaubitz, frank.li,
tytso, adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
On Tue, Jan 13, 2026 at 2:46 AM Chuck Lever <cel@kernel.org> wrote:
>
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Report exFAT's case sensitivity behavior via the file_kattr boolean
> fields. exFAT is always case-insensitive (using an upcase table for
> comparison) and always preserves case at rest.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Thanks!
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 16/16] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION
2026-01-12 17:46 ` [PATCH v3 16/16] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION Chuck Lever
@ 2026-01-14 0:46 ` Namjae Jeon
0 siblings, 0 replies; 30+ messages in thread
From: Namjae Jeon @ 2026-01-14 0:46 UTC (permalink / raw)
To: Chuck Lever
Cc: Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4, linux-xfs,
linux-cifs, linux-nfs, linux-f2fs-devel, hirofumi, sj1557.seo,
yuezhang.mo, almaz.alexandrovich, slava, glaubitz, frank.li,
tytso, adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever
On Tue, Jan 13, 2026 at 2:47 AM Chuck Lever <cel@kernel.org> wrote:
>
> From: Chuck Lever <chuck.lever@oracle.com>
>
> ksmbd hard-codes FILE_CASE_SENSITIVE_SEARCH and
> FILE_CASE_PRESERVED_NAMES in FS_ATTRIBUTE_INFORMATION responses,
> incorrectly indicating all exports are case-sensitive. This breaks
> clients accessing case-insensitive filesystems like exFAT or
> ext4/f2fs directories with casefold enabled.
>
> Query actual case behavior via vfs_fileattr_get() and report accurate
> attributes to SMB clients. 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.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Thanks!
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 11/16] f2fs: Add case sensitivity reporting to fileattr_get
2026-01-12 17:46 ` [PATCH v3 11/16] f2fs: Add case sensitivity reporting to fileattr_get Chuck Lever
@ 2026-01-14 0:50 ` Chao Yu
0 siblings, 0 replies; 30+ messages in thread
From: Chao Yu @ 2026-01-14 0:50 UTC (permalink / raw)
To: Chuck Lever, Christian Brauner, Jan Kara
Cc: chao, linux-fsdevel, linux-ext4, linux-xfs, linux-cifs, linux-nfs,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, hansg, senozhatsky, Chuck Lever
On 1/13/2026 1:46 AM, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> NFS and other remote filesystem protocols need to determine
> whether a local filesystem performs case-insensitive lookups
> so they can provide correct semantics to clients. Without
> this information, f2fs exports cannot properly advertise
> their filename case behavior.
>
> Report f2fs case sensitivity behavior via the file_kattr
> boolean fields. Like ext4, f2fs supports per-directory case
> folding via the casefold flag (IS_CASEFOLDED). Files are
> always case-preserving.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Thanks,
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2026-01-14 0:50 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-12 17:46 [PATCH v3 00/16] Exposing case folding behavior Chuck Lever
2026-01-12 17:46 ` [PATCH v3 01/16] fs: Add case sensitivity info to file_kattr Chuck Lever
2026-01-13 15:21 ` Christoph Hellwig
2026-01-12 17:46 ` [PATCH v3 02/16] fat: Implement fileattr_get for case sensitivity Chuck Lever
2026-01-13 15:23 ` Christoph Hellwig
2026-01-12 17:46 ` [PATCH v3 03/16] exfat: " Chuck Lever
2026-01-14 0:45 ` Namjae Jeon
2026-01-12 17:46 ` [PATCH v3 04/16] ntfs3: " Chuck Lever
2026-01-12 17:46 ` [PATCH v3 05/16] hfs: " Chuck Lever
2026-01-13 17:35 ` Viacheslav Dubeyko
2026-01-12 17:46 ` [PATCH v3 06/16] hfsplus: Report case sensitivity in fileattr_get Chuck Lever
2026-01-13 17:36 ` Viacheslav Dubeyko
2026-01-12 17:46 ` [PATCH v3 07/16] ext4: " Chuck Lever
2026-01-13 11:50 ` Jan Kara
2026-01-12 17:46 ` [PATCH v3 08/16] xfs: " Chuck Lever
2026-01-13 16:02 ` Darrick J. Wong
2026-01-13 16:43 ` Neal Gompa
2026-01-12 17:46 ` [PATCH v3 09/16] cifs: Implement fileattr_get for case sensitivity Chuck Lever
2026-01-12 17:46 ` [PATCH v3 10/16] nfs: " Chuck Lever
2026-01-12 17:46 ` [PATCH v3 11/16] f2fs: Add case sensitivity reporting to fileattr_get Chuck Lever
2026-01-14 0:50 ` Chao Yu
2026-01-12 17:46 ` [PATCH v3 12/16] vboxsf: Implement fileattr_get for case sensitivity Chuck Lever
2026-01-12 17:46 ` [PATCH v3 13/16] isofs: " Chuck Lever
2026-01-13 11:50 ` Jan Kara
2026-01-12 17:46 ` [PATCH v3 14/16] nfsd: Report export case-folding via NFSv3 PATHCONF Chuck Lever
2026-01-12 17:46 ` [PATCH v3 15/16] nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING Chuck Lever
2026-01-12 17:46 ` [PATCH v3 16/16] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION Chuck Lever
2026-01-14 0:46 ` Namjae Jeon
2026-01-13 9:04 ` [PATCH v3 00/16] Exposing case folding behavior Christian Brauner
2026-01-13 13:58 ` Chuck Lever
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox