Exposing case folding behavior
Subsystems (6)
Chuck Lever
maintainerv2 cover Exposing case folding behavior
From: Chuck Lever <[email protected]>
Following on from
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
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 (6):
fs: Add case sensitivity info to file_kattr
fat: Implement fileattr_get for case sensitivity
ntfs3: Implement fileattr_get for case sensitivity
ext4: Report case sensitivity in fileattr_get
nfsd: Report export case-folding via NFSv3 PATHCONF
nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and
FATTR4_CASE_PRESERVING
fs/ext4/ioctl.c | 12 ++++++++++++ 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 | 31 +++++++++++++++++++++++++++++++ fs/nfsd/nfs3proc.c | 18 ++++++++++-------- fs/nfsd/nfs4xdr.c | 30 ++++++++++++++++++++++++++---- fs/nfsd/vfs.c | 25 +++++++++++++++++++++++++ fs/nfsd/vfs.h | 2 ++ fs/ntfs3/file.c | 27 +++++++++++++++++++++++++++ fs/ntfs3/inode.c | 1 + fs/ntfs3/namei.c | 2 ++ fs/ntfs3/ntfs_fs.h | 1 + include/linux/fileattr.h | 23 +++++++++++++++++++++++ 15 files changed, 183 insertions(+), 12 deletions(-)
Signature · 1 line
2.52.0
Chuck Lever
maintainerPATCH v2 1/6 fs: Add case sensitivity info to file_kattr
From: Chuck Lever <[email protected]>
Enable upper layers such as NFSD to retrieve case sensitivity information from file systems by adding a case_info field to struct file_kattr.
Add vfs_get_case_info() as a convenience helper for kernel consumers. If a filesystem does not provide a fileattr_get hook, it returns the default POSIX behavior (case-sensitive, case-preserving), which is correct for the majority of Linux file systems implementations.
--- fs/file_attr.c | 31 +++++++++++++++++++++++++++++++ include/linux/fileattr.h | 23 +++++++++++++++++++++++ 2 files changed, 54 insertions(+)
fs/file_attr.c +31 -0
@@ -94,6 +94,37 @@ int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) }EXPORT_SYMBOL (vfs_fileattr_get); +/** +* vfs_get_case_info - retrieve case sensitivity info for a filesystem +* @dentry: the object to retrieve from +* @case_info: pointer to store result +* +* Call i_op->fileattr_get() to retrieve case sensitivity information. +* If the filesystem does not provide a fileattr_get hook, return +* the default POSIX behavior (case-sensitive, case-preserving). +* +* Return: 0 on success, or a negative error on failure. +*/ +int vfs_get_case_info (struct dentry *dentry,u32 *case_info) +{ +struct file_kattr fa = {}; +int error; + +/* Default: POSIX semantics (case-sensitive, case-preserving) */ + *case_info =FILEATTR_CASEFOLD_NONE |FILEATTR_CASE_PRESERVING ; + + error =vfs_fileattr_get (dentry, &fa); +if (error == -ENOIOCTLCMD ) +return 0 ; +if (error) +return error; + +if (fa.case_info) + *case_info = fa.case_info; +return 0 ; +} +EXPORT_SYMBOL (vfs_get_case_info); +static void fileattr_to_file_attr (const struct file_kattr *fa,struct file_attr *fattr) {
include/linux/fileattr.h +23 -0
@@ -48,11 +48,33 @@ struct file_kattr {u32 fsx_nextents;/* nextents field value (get) */ u32 fsx_projid;/* project identifier (get/set) */ u32 fsx_cowextsize;/* CoW extsize field value (get/set)*/ +u32 case_info;/* case sensitivity behavior */ /* selectors: */ bool flags_valid:1; bool fsx_valid:1; }; +/* +* Values for file_kattr.case_info. +*/ + +/* File name case is preserved at rest. */ +#define FILEATTR_CASE_PRESERVING 0x80000000 + +/* Values stored in the low-order byte */ +enum fileattr_case_folding { +/* Code points are compared directly with no case folding. */ +FILEATTR_CASEFOLD_NONE =0 , + +/* ASCII case-insensitive: A-Z are treated as a-z. */ +FILEATTR_CASEFOLD_ASCII , + +/* Unicode case-insensitive matching. */ +FILEATTR_CASEFOLD_UNICODE , +}; + +#define FILEATTR_CASEFOLD_TYPE 0x000000ff +int copy_fsxattr_to_user (const struct file_kattr *fa,struct fsxattr __user *ufa);void fileattr_fill_xflags (struct file_kattr *fa,u32 xflags);
@@ -75,6 +97,7 @@ static inline bool fileattr_has_fsx(const struct file_kattr *fa)int vfs_fileattr_get (struct dentry *dentry,struct file_kattr *fa);int vfs_fileattr_set (struct mnt_idmap *idmap,struct dentry *dentry,struct file_kattr *fa); +int vfs_get_case_info (struct dentry *dentry,u32 *case_info);int ioctl_getflags (struct file *file,unsigned int __user *argp);int ioctl_setflags (struct file *file,unsigned int __user *argp);int ioctl_fsgetxattr (struct file *file,void __user *argp);
Signature · 1 line
2.52.0
Re: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
include/linux/fileattr.h struct file_kattr { · line 74
Quoted 11 lines · Chuck Lever
include/linux/fileattr.h +11
-0+/* Values stored in the low-order byte */ +enum fileattr_case_folding { +/* Code points are compared directly with no case folding. */ +FILEATTR_CASEFOLD_NONE =0 , + +/* ASCII case-insensitive: A-Z are treated as a-z. */ +FILEATTR_CASEFOLD_ASCII , + +/* Unicode case-insensitive matching. */ +FILEATTR_CASEFOLD_UNICODE , +};
What does "Unicode case-insensitive matching" mean? There are many different things it could mean: there are multiple types of Unicode normalization, Unicode case-folding, NTFS's upper case table, etc. There are also multiple versions of each.
I see you're proposing that ext4, fat, and ntfs3 all set FILEATTR_CASEFOLD_UNICODE, at least in some cases.
That seems odd, since they don't do the matching the same way.
- Eric
Chuck Lever
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
Quoted 17 lines · Eric Biggers
include/linux/fileattr.h struct file_kattr { · line 74
Quoted 11 lines · Chuck Lever
include/linux/fileattr.h +11
-0+/* Values stored in the low-order byte */ +enum fileattr_case_folding { +/* Code points are compared directly with no case folding. */ +FILEATTR_CASEFOLD_NONE =0 , + +/* ASCII case-insensitive: A-Z are treated as a-z. */ +FILEATTR_CASEFOLD_ASCII , + +/* Unicode case-insensitive matching. */ +FILEATTR_CASEFOLD_UNICODE , +};What does "Unicode case-insensitive matching" mean? There are many different things it could mean: there are multiple types of Unicode normalization, Unicode case-folding, NTFS's upper case table, etc. There are also multiple versions of each.
This is left over from the RFC version of the series, and can be removed.
Quoted 4 lines
I see you're proposing that ext4, fat, and ntfs3 all set
FILEATTR_CASEFOLD_UNICODE, at least in some cases.That seems odd, since they don't do the matching the same way.
The purpose of this series is to design the VFS infrastructure. Exactly what it reports is up to folks who actually understand i18n.
Signature · 1 line
Chuck Lever
Theodore Tso
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
Quoted 8 lines · Chuck Lever
Quoted 5 lines
I see you're proposing that ext4, fat, and ntfs3 all set
FILEATTR_CASEFOLD_UNICODE, at least in some cases.That seems odd, since they don't do the matching the same way.
The purpose of this series is to design the VFS infrastructure. Exactly what it reports is up to folks who actually understand i18n.
Do we know who would be receiving this information and what their needs might be?
- Ted
Chuck Lever
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
Quoted 5 lines · Theodore Tso
Quoted 4 lines · Chuck Lever
Quoted 4 lines
I see you're proposing that ext4, fat, and ntfs3 all set
FILEATTR_CASEFOLD_UNICODE, at least in some cases.
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
That seems odd, since they don't do the matching the same way.
The purpose of this series is to design the VFS infrastructure. Exactly what it reports is up to folks who actually understand i18n.
Do we know who would be receiving this information and what their needs might be?
The unicode v. ascii case folding information was included just as an example. I don't have any use case for that, and as I told Eric, those specifics can be removed from the API.
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.
I'm told that Samba has to detect and expose file system case folding behavior to its clients as well. Supporting Samba and other user space file servers is why this series exposes case folding information via a local 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.
As a side note: I assumed these details were already well-known in this community; otherwise I would have included it in the series cover letter. I can include it when posting subsequent revisions.
Signature · 5 lines
Chuck Lever [1] https://github.com/kofemann/ms-nfs41-client [2] https://patchwork.kernel.org/project/linux-nfs/cover/[email protected]/
Theodore Tso
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
Quoted 8 lines · Chuck Lever
The unicode v. ascii case folding information was included just as an example. I don't have any use case for that, and as I told Eric, those specifics can be removed from the API.
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.
I was worried that some clients might be using this information so they could do informed caching --- i,e., if they have "makefile" cached locally because the user typed "more < makefile" into their Windows Command.exe window, and then later on some program tries to access "Makefile" the client OS might decide that they "know" that "makefile" and "Makefile" are the same file. But if that's the case, then it needs to have more details about whether it's ASCII versus Unicode 1.0 vs Unicode 17.0 case folding that be in use, or there might be "interesting" corner cases.
Which is why I've gotten increasingly more sympathetic to Linus's position that case folding is Hot Trash. If it weren't for the fact that I really wanted to get Android out of using wrapfs (which is an even greater trash fire), I'd be regretting the fact that I helped to add insensitive file name support to Linux...
- Ted
Trond Myklebust
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
Quoted 10 lines · Theodore Tso
Quoted 8 lines · Chuck Lever
The unicode v. ascii case folding information was included just as an example. I don't have any use case for that, and as I told Eric, those specifics can be removed from the API.
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.
Quoted 9 lines
I was worried that some clients might be using this information so they could do informed caching --- i,e., if they have "makefile" cached locally because the user typed "more < makefile" into their Windows Command.exe window, and then later on some program tries to access "
Makefile" the client OS might decide that they "know" that "makefile" and "Makefile" are the same file. But if that's the case, then it needs to have more details about whether it's ASCII versus Unicode 1.0 vs Unicode 17.0 case folding that be in use, or there might be "interesting" corner cases.
The Linux NFSv4 client has no clue about how to fold cases so, as Chuck indicated, it uses the case insensitivity flag only to know when to be more aggressive about revalidating cached positive dentries and/or evicting cached negative dentries after the directory contents are seen to change.
As of now, I'm aware of no plans to try to implement anything like the "informed caching" you describe above.
Quoted 7 lines
Which is why I've gotten increasingly more sympathetic to Linus's position that case folding is Hot Trash. If it weren't for the fact that I really wanted to get Android out of using wrapfs (which is an even greater trash fire), I'd be regretting the fact that I helped to add insensitive file name support to Linux...
- Ted
Signature · 3 lines
Trond Myklebust Linux NFS client maintainer, Hammerspace [email protected], [email protected]
Chuck Lever
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
In reply to Theodore TsoQuoted 10 lines · Theodore Tso
Quoted 8 lines · Chuck Lever
The unicode v. ascii case folding information was included just as an example. I don't have any use case for that, and as I told Eric, those specifics can be removed from the API.
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.
Quoted 9 lines
I was worried that some clients might be using this information so they could do informed caching --- i,e., if they have "makefile" cached locally because the user typed "more < makefile" into their Windows Command.exe window, and then later on some program tries to access "
Makefile" the client OS might decide that they "know" that "makefile" and "Makefile" are the same file. But if that's the case, then it needs to have more details about whether it's ASCII versus Unicode 1.0 vs Unicode 17.0 case folding that be in use, or there might be "interesting" corner cases.
No current version of the NFS protocol can communicate any more than whether or not filenames are case sensitive and case preserving. Thus the unicode label idea is nothing NFSD can possibly take advantage of.
Quoted 5 lines
Which is why I've gotten increasingly more sympathetic to Linus's position that case folding is Hot Trash. If it weren't for the fact that I really wanted to get Android out of using wrapfs (which is an even greater trash fire), I'd be regretting the fact that I helped to add insensitive file name support to Linux...
Well I think "Hot Trash" is the general consensus. I'm not thinking of adding more than the NFS protocol can support. I'm only suggesting that more /could/ be done if someone has a use case for it.
Signature · 1 line
Chuck Lever
Christian Brauner
maintainerRe: [PATCH v2 1/6] fs: Add case sensitivity info to file_kattr
In reply to Chuck LeverQuoted 6 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Enable upper layers such as NFSD to retrieve case sensitivity information from file systems by adding a
case_infofield to structfile_kattr.
Quoted 8 lines
Add
vfs_get_case_info()as a convenience helper for kernel consumers. If a filesystem does not provide afileattr_gethook, it returns the default POSIX behavior (case-sensitive, case-preserving), which is correct for the majority of Linux file systems implementations.Signed-off-by Chuck Lever <[email protected]>---
Thanks for listening and plumbing this into file_attr() that seems a much better place than statx().
Quoted 14 lines
fs/file_attr.c | 31 +++++++++++++++++++++++++++++++ include/linux/fileattr.h | 23 +++++++++++++++++++++++ 2 files changed, 54 insertions(+)fs/file_attr.c +2
-0@@ -94,6 +94,37 @@ int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) }EXPORT_SYMBOL (vfs_fileattr_get); +/** +* vfs_get_case_info - retrieve case sensitivity info for a filesystem
fs/file_attr.c int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) · line 108
Quoted 10 lines
fs/file_attr.c +10
-0+* @dentry: the object to retrieve from +* @case_info: pointer to store result +* +* Call i_op->fileattr_get() to retrieve case sensitivity information. +* If the filesystem does not provide a fileattr_get hook, return +* the default POSIX behavior (case-sensitive, case-preserving). +* +* Return: 0 on success, or a negative error on failure. +*/ +int vfs_get_case_info (struct dentry *dentry,u32 *case_info)
Hm, I would much prefer if we followed the statx() model where we have vfs_getattr{_nosec}() that always returns a struct kstat. So we should only have vfs_fileattr_get() instead of the special-purpose vfs_get_case_info() thing.
I guess the main reason you did this is so that you can set the default without having to touch each filesystem that doesn't do file_attr.
So just move the default setup of case_info into vfs_fileattr_get()? This way it's also available to other callers of this function such as overlayfs and ecryptfs. And then just call that in nfsd.
Otherwise I have no complaints about the VFS part.
Chuck Lever
maintainerPATCH v2 2/6 fat: Implement fileattr_get for case sensitivity
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
Report FAT's case sensitivity behavior via the new file_kattr case_info field. FAT filesystems are case-insensitive and do not preserve case at rest (stored names are uppercased).
The case folding type depends on the mount options: when utf8 is enabled, Unicode case folding is used; otherwise ASCII case folding.
--- 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(+)
fs/fat/fat.h +3 -0
@@ -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);
fs/fat/file.c +18 -0
@@ -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 inode *inode =d_inode (dentry); +struct msdos_sb_info *sbi =MSDOS_SB (inode->i_sb); + +/* +* FAT filesystems do not preserve case: stored names are +* uppercased. They are case-insensitive, using either ASCII +* or Unicode comparison depending on mount options. +*/ + fa->case_info = sbi->options.utf8 ? +FILEATTR_CASEFOLD_UNICODE :FILEATTR_CASEFOLD_ASCII ; +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, };
fs/fat/namei_msdos.c +1 -0
@@ -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, };
fs/fat/namei_vfat.c +1 -0
@@ -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, };
Signature · 1 line
2.52.0
OGAWA Hirofumi
maintainerRe: [PATCH v2 2/6] fat: Implement fileattr_get for case sensitivity
Quoted 10 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Report FAT's case sensitivity behavior via the new
file_kattrcase_infofield. FAT filesystems are case-insensitive and do not preserve case at rest (stored names are uppercased).The case folding type depends on the mount options: when utf8 is enabled, Unicode case folding is used; otherwise ASCII case folding.
Signed-off-by Chuck Lever <[email protected]>
I can't see the who and how to use this though, in msdos case, looks like this should check "nocase" option.
Thanks.
Quoted 93 lines
--- 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(+)fs/fat/fat.h +3
-0@@ -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);fs/fat/file.c +18
-0@@ -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 inode *inode =d_inode (dentry); +struct msdos_sb_info *sbi =MSDOS_SB (inode->i_sb); + +/* +* FAT filesystems do not preserve case: stored names are +* uppercased. They are case-insensitive, using either ASCII +* or Unicode comparison depending on mount options. +*/ + fa->case_info = sbi->options.utf8 ? +FILEATTR_CASEFOLD_UNICODE :FILEATTR_CASEFOLD_ASCII ; +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, };fs/fat/namei_msdos.c +1
-0@@ -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, };fs/fat/namei_vfat.c +1
-0@@ -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, };
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Chuck Lever
maintainerPATCH v2 3/6 ntfs3: Implement fileattr_get for case sensitivity
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
Report NTFS case sensitivity behavior via the new file_kattr case_info field. NTFS always preserves case at rest.
Case sensitivity depends on mount options: with "nocase", NTFS performs Unicode case-insensitive matching; otherwise it is case-sensitive.
--- fs/ntfs3/file.c | 27 +++++++++++++++++++++++++++ fs/ntfs3/inode.c | 1 + fs/ntfs3/namei.c | 2 ++ fs/ntfs3/ntfs_fs.h | 1 + 4 files changed, 31 insertions(+)
fs/ntfs3/file.c +27 -0
@@ -104,6 +104,32 @@ 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 using +* Unicode case folding; otherwise it is case-sensitive. +*/ +if (sbi->options && sbi->options->nocase) + fa->case_info =FILEATTR_CASEFOLD_UNICODE | +FILEATTR_CASE_PRESERVING ; +else + fa->case_info =FILEATTR_CASEFOLD_NONE | +FILEATTR_CASE_PRESERVING ; +return 0 ; +} +/* * ntfs_getattr - inode_operations::getattr */
@@ -1383,6 +1409,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 = {
fs/ntfs3/inode.c +1 -0
@@ -2085,6 +2085,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 = {
fs/ntfs3/namei.c +2 -0
@@ -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 = {
fs/ntfs3/ntfs_fs.h +1 -0
@@ -503,6 +503,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,
Signature · 1 line
2.52.0
Chuck Lever
maintainerPATCH v2 4/6 ext4: Report case sensitivity in fileattr_get
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
Report ext4's case sensitivity behavior via file_kattr.case_info. ext4 always preserves case at rest.
Case sensitivity is a per-directory setting in ext4. If the queried inode is a casefolded directory, report Unicode case-insensitive matching; otherwise report case-sensitive (standard POSIX behavior).
This enables file_getattr to report the case sensitivity behavior of individual directories within an ext4 filesystem.
--- fs/ext4/ioctl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
fs/ext4/ioctl.c +12 -0
@@ -996,6 +996,18 @@ 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 Unicode case-insensitive; otherwise +* report case-sensitive (standard POSIX behavior). +*/ +if (IS_CASEFOLDED (inode)) + fa->case_info =FILEATTR_CASEFOLD_UNICODE | +FILEATTR_CASE_PRESERVING ; +else + fa->case_info =FILEATTR_CASEFOLD_NONE | +FILEATTR_CASE_PRESERVING ; +return 0 ; }
Signature · 1 line
2.52.0
Chuck Lever
maintainerPATCH v2 5/6 nfsd: Report export case-folding via NFSv3 PATHCONF
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
Replace the hard-coded MSDOS_SUPER_MAGIC check in nfsd3_proc_pathconf() with a real check of the export's case behavior settings. Filesystems that implement ->fileattr_get can then report their case sensitivity behavior to NFSv3 clients. For filesystems without ->fileattr_get, the default POSIX behavior (case-sensitive, case-preserving) is reported to NFSv3 clients.
--- fs/nfsd/nfs3proc.c | 18 ++++++++++-------- fs/nfsd/vfs.c | 25 +++++++++++++++++++++++++ fs/nfsd/vfs.h | 2 ++ 3 files changed, 37 insertions(+), 8 deletions(-)
fs/nfsd/nfs3proc.c +10 -8
@@ -721,17 +721,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; } }
fs/nfsd/vfs.c +25 -0
@@ -32,6 +32,7 @@#include <linux/writeback.h> #include <linux/security.h> #include <linux/sunrpc/xdr.h> +#include <linux/fileattr.h> #include "xdr3.h"
@@ -2679,3 +2680,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) +{ +u32 case_info; +int err; + + err =vfs_get_case_info (fhp->fh_dentry, &case_info); +if (err) +return nfserrno (err); + + *case_insensitive = (case_info &FILEATTR_CASEFOLD_TYPE ) !=0 ; + *case_preserving = (case_info &FILEATTR_CASE_PRESERVING ) !=0 ; +return nfs_ok; +}
fs/nfsd/vfs.h +2 -0
@@ -154,6 +154,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);
Signature · 1 line
2.52.0
Chuck Lever
maintainerPATCH v2 6/6 nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
Replace the hard-coded values for the NFSv4 case_insensitive and case_preserving attributes with dynamic values retrieved from the underlying filesystem via vfs_get_case_info().
This allows NFSv4 clients to discover the actual case sensitivity behavior of exported filesystems, including per-directory settings for filesystems like ext4 with casefold support.
--- fs/nfsd/nfs4xdr.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-)
fs/nfsd/nfs4xdr.c +26 -4
@@ -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) {
@@ -3482,8 +3496,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,
@@ -3669,8 +3683,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)
@@ -3682,6 +3697,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);
Signature · 1 line
2.52.0
Quoted 1 line · Chuck Lever
- Support NTFS and ext4 in addition to FAT
Still missing at least xfs, hfs, hfsplus and exfat, nfs and cifs.