From: Chuck Lever Enable upper layers such as NFSD to retrieve case sensitivity information from file systems by adding case_insensitive and case_nonpreserving boolean fields to struct file_kattr. These fields default to false (POSIX semantics: case-sensitive and case-preserving), allowing filesystems to set them only when behavior differs from the default. Signed-off-by: Chuck Lever --- fs/file_attr.c | 14 ++++++++++++++ include/linux/fileattr.h | 3 +++ include/uapi/linux/fs.h | 12 +++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/fs/file_attr.c b/fs/file_attr.c index 13cdb31a3e94..df4b2fc68532 100644 --- a/fs/file_attr.c +++ b/fs/file_attr.c @@ -84,6 +84,8 @@ int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) struct inode *inode = d_inode(dentry); int error; + memset(fa, 0, sizeof(*fa)); + if (!inode->i_op->fileattr_get) return -ENOIOCTLCMD; @@ -106,6 +108,10 @@ static void fileattr_to_file_attr(const struct file_kattr *fa, fattr->fa_nextents = fa->fsx_nextents; fattr->fa_projid = fa->fsx_projid; fattr->fa_cowextsize = fa->fsx_cowextsize; + if (fa->case_insensitive) + fattr->fa_case_behavior |= FS_CASE_INSENSITIVE; + if (fa->case_nonpreserving) + fattr->fa_case_behavior |= FS_CASE_NONPRESERVING; } /** @@ -382,6 +388,10 @@ SYSCALL_DEFINE5(file_getattr, int, dfd, const char __user *, filename, BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0); BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST); + BUILD_BUG_ON(offsetofend(struct file_attr, fa_cowextsize) != + FILE_ATTR_SIZE_VER0); + BUILD_BUG_ON(offsetofend(struct file_attr, fa_reserved) != + FILE_ATTR_SIZE_VER1); if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) return -EINVAL; @@ -439,6 +449,10 @@ SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename, BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0); BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST); + BUILD_BUG_ON(offsetofend(struct file_attr, fa_cowextsize) != + FILE_ATTR_SIZE_VER0); + BUILD_BUG_ON(offsetofend(struct file_attr, fa_reserved) != + FILE_ATTR_SIZE_VER1); if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) return -EINVAL; diff --git a/include/linux/fileattr.h b/include/linux/fileattr.h index f89dcfad3f8f..086f28b90734 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_nonpreserving:1; }; int copy_fsxattr_to_user(const struct file_kattr *fa, struct fsxattr __user *ufa); diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 66ca526cf786..07286d34b48b 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -229,10 +229,20 @@ struct file_attr { __u32 fa_nextents; /* nextents field value (get) */ __u32 fa_projid; /* project identifier (get/set) */ __u32 fa_cowextsize; /* CoW extsize field value (get/set) */ + /* VER1 additions: */ + __u32 fa_case_behavior; /* case sensitivity (get) */ + __u32 fa_reserved; }; #define FILE_ATTR_SIZE_VER0 24 -#define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER0 +#define FILE_ATTR_SIZE_VER1 32 +#define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER1 + +/* + * Case sensitivity flags for fa_case_behavior + */ +#define FS_CASE_INSENSITIVE 0x00000001 /* case-insensitive lookups */ +#define FS_CASE_NONPRESERVING 0x00000002 /* case not preserved */ /* * Flags for the fsx_xflags field -- 2.52.0