Prepare for upcoming Casefolding/Encryption patches
Subsystems (5)
v12 cover Prepare for upcoming Casefolding/Encryption patches
This lays the ground work for enabling casefolding and encryption at the same time for ext4 and f2fs. A future set of patches will enable that functionality.
These unify the highly similar dentry_operations that ext4 and f2fs both use for casefolding. In addition, they improve d_hash by not requiring a new string allocation.
Daniel Rosenberg (4):
unicode: Add utf8_casefold_hash
fs: Add standard casefolding support
f2fs: Use generic casefolding support
ext4: Use generic casefolding support
fs/ext4/dir.c | 64 +----------------------------- fs/ext4/ext4.h | 12 ------ fs/ext4/hash.c | 2 +- fs/ext4/namei.c | 20 ++++------ fs/ext4/super.c | 12 +++--- fs/f2fs/dir.c | 84 +++++---------------------------------- fs/f2fs/f2fs.h | 4 -- fs/f2fs/super.c | 10 ++--- fs/f2fs/sysfs.c | 10 +++-- fs/libfs.c | 87 +++++++++++++++++++++++++++++++++++++++++ fs/unicode/utf8-core.c | 23 ++++++++++- include/linux/f2fs_fs.h | 3 -- include/linux/fs.h | 16 ++++++++ include/linux/unicode.h | 3 ++ 14 files changed, 165 insertions(+), 185 deletions(-)
Signature · 1 line
2.27.0.383.g050319c2ae-goog
PATCH v12 1/4 unicode: Add utf8_casefold_hash
This adds a case insensitive hash function to allow taking the hash without needing to allocate a casefolded copy of the string.
The existing d_hash implementations for casefolding allocate memory within rcu-walk, by avoiding it we can be more efficient and avoid worrying about a failed allocation.
--- fs/unicode/utf8-core.c | 23 ++++++++++++++++++++++- include/linux/unicode.h | 3 +++ 2 files changed, 25 insertions(+), 1 deletion(-)
fs/unicode/utf8-core.c +22 -1
@@ -6,6 +6,7 @@#include <linux/parser.h> #include <linux/errno.h> #include <linux/unicode.h> +#include <linux/stringhash.h> #include "utf8n.h"
@@ -122,9 +123,29 @@ int utf8_casefold(const struct unicode_map *um, const struct qstr *str, }return -EINVAL ; } -EXPORT_SYMBOL (utf8_casefold); +int utf8_casefold_hash (const struct unicode_map *um,const void *salt, +struct qstr *str) +{ +const struct utf8data *data =utf8nfdicf (um->version); +struct utf8cursor cur; +int c; +unsigned long hash =init_name_hash (salt); + +if (utf8ncursor (&cur, data, str->name, str->len) <0 ) +return -EINVAL ; + +while ((c =utf8byte (&cur))) { +if (c <0 ) +return -EINVAL ; + hash =partial_name_hash ((unsigned char )c, hash); + } + str->hash =end_name_hash (hash); +return 0 ; +} +EXPORT_SYMBOL (utf8_casefold_hash); +int utf8_normalize (const struct unicode_map *um,const struct qstr *str,unsigned char *dest,size_t dlen) {
include/linux/unicode.h +3 -0
@@ -27,6 +27,9 @@ int utf8_normalize(const struct unicode_map *um, const struct qstr *str,int utf8_casefold (const struct unicode_map *um,const struct qstr *str,unsigned char *dest,size_t dlen); +int utf8_casefold_hash (const struct unicode_map *um,const void *salt, +struct qstr *str); +struct unicode_map *utf8_load (const char *version);void utf8_unload (struct unicode_map *um);
Signature · 1 line
2.27.0.383.g050319c2ae-goog
PATCH v12 2/4 fs: Add standard casefolding support
In reply to Daniel RosenbergThis adds general supporting functions for filesystems that use utf8 casefolding. It provides standard dentry_operations and adds the necessary structures in struct super_block to allow this standardization.
The new dentry operations are functionally equivalent to the existing operations in ext4 and f2fs, apart from the use of utf8_casefold_hash to avoid an allocation.
By providing a common implementation, all users can benefit from any optimizations without needing to port over improvements.
--- fs/libfs.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 16 +++++++++ 2 files changed, 103 insertions(+)
fs/libfs.c +87 -0
@@ -20,6 +20,8 @@#include <linux/fs_context.h> #include <linux/pseudo_fs.h> #include <linux/fsnotify.h> +#include <linux/unicode.h> +#include <linux/fscrypt.h> #include <linux/uaccess.h>
@@ -1363,3 +1365,88 @@ bool is_empty_dir_inode(struct inode *inode)return (inode->i_fop == &empty_dir_operations) && (inode->i_op == &empty_dir_inode_operations); } + +#ifdef CONFIG_UNICODE +/* +* Determine if the name of a dentry should be casefolded. +* +* Return: if names will need casefolding +*/ +static bool needs_casefold (const struct inode *dir) +{ +return IS_CASEFOLDED (dir) && dir->i_sb->s_encoding; +} + +/** +* generic_ci_d_compare - generic d_compare implementation for casefolding filesystems +* @dentry: dentry whose name we are checking against +* @len: len of name of dentry +* @str: str pointer to name of dentry +* @name: Name to compare against +* +* Return: 0 if names match, 1 if mismatch, or -ERRNO +*/ +int generic_ci_d_compare (const struct dentry *dentry,unsigned int len, +const char *str,const struct qstr *name) +{ +const struct dentry *parent =READ_ONCE (dentry->d_parent); +const struct inode *dir =READ_ONCE (parent->d_inode); +const struct super_block *sb = dentry->d_sb; +const struct unicode_map *um = sb->s_encoding; +struct qstr qstr =QSTR_INIT (str, len); +char strbuf[DNAME_INLINE_LEN ]; +int ret; + +if (!dir || !needs_casefold (dir)) + goto fallback; +/* +* If the dentry name is stored in-line, then it may be concurrently +* modified by a rename. If this happens, the VFS will eventually retry +* the lookup, so it doesn't matter what ->d_compare() returns. +* However, it's unsafe to call utf8_strncasecmp() with an unstable +* string. Therefore, we have to copy the name into a temporary buffer. +*/ +if (len <=DNAME_INLINE_LEN -1 ) { +memcpy (strbuf, str, len); + strbuf[len] =0 ; + qstr.name = strbuf; +/* prevent compiler from optimizing out the temporary buffer */ +barrier (); + } + ret =utf8_strncasecmp (um, name, &qstr); +if (ret >=0 ) +return ret; + +if (sb_has_strict_encoding (sb)) +return -EINVAL ; +fallback: +if (len != name->len) +return 1 ; +return !!memcmp (str, name->name, len); +} +EXPORT_SYMBOL (generic_ci_d_compare); + +/** +* generic_ci_d_hash - generic d_hash implementation for casefolding filesystems +* @dentry: dentry of the parent directory +* @str: qstr of name whose hash we should fill in +* +* Return: 0 if hash was successful or unchanged, and -EINVAL on error +*/ +int generic_ci_d_hash (const struct dentry *dentry,struct qstr *str) +{ +const struct inode *dir =READ_ONCE (dentry->d_inode); +struct super_block *sb = dentry->d_sb; +const struct unicode_map *um = sb->s_encoding; +int ret =0 ; + +if (!dir || !needs_casefold (dir)) +return 0 ; + + ret =utf8_casefold_hash (um, dentry, str); +if (ret <0 &&sb_has_strict_encoding (sb)) +return -EINVAL ; +return 0 ; +} +EXPORT_SYMBOL (generic_ci_d_hash); +#endif
include/linux/fs.h +16 -0
@@ -1392,6 +1392,12 @@ extern int send_sigurg(struct fown_struct *fown);#define SB_ACTIVE (1<<30)#define SB_NOUSER (1<<31) +/* These flags relate to encoding and casefolding */ +#define SB_ENC_STRICT_MODE_FL (1 << 0) + +#define sb_has_strict_encoding (sb) \ + (sb->s_encoding_flags & SB_ENC_STRICT_MODE_FL) +/* * Umount options */
@@ -1461,6 +1467,10 @@ struct super_block {#endif #ifdef CONFIG_FS_VERITY const struct fsverity_operations *s_vop; +#endif +#ifdef CONFIG_UNICODE +struct unicode_map *s_encoding; +__u16 s_encoding_flags;#endif struct hlist_bl_head s_roots;/* alternate root dentries for NFS */ struct list_head s_mounts;/* list of mounts; _not_ for fs use */
@@ -3385,6 +3395,12 @@ extern int generic_file_fsync(struct file *, loff_t, loff_t, int);extern int generic_check_addressable (unsigned ,u64 ); +#ifdef CONFIG_UNICODE +extern int generic_ci_d_hash (const struct dentry *dentry,struct qstr *str); +extern int generic_ci_d_compare (const struct dentry *dentry,unsigned int len, +const char *str,const struct qstr *name); +#endif +#ifdef CONFIG_MIGRATION extern int buffer_migrate_page(struct address_space *, struct page *, struct page *,
Signature · 1 line
2.27.0.383.g050319c2ae-goog
Re: [PATCH v12 2/4] fs: Add standard casefolding support
Quoted 4 lines · Daniel Rosenberg
This adds general supporting functions for filesystems that use utf8 casefolding. It provides standard
dentry_operationsand adds the necessary structures in structsuper_blockto allow this standardization.
Quoted 8 lines
The new dentry operations are functionally equivalent to the existing operations in ext4 and f2fs, apart from the use of
utf8_casefold_hashto avoid an allocation.By providing a common implementation, all users can benefit from any optimizations without needing to port over improvements.
Signed-off-by Daniel Rosenberg <[email protected]>
PATCH v12 3/4 f2fs: Use generic casefolding support
In reply to Daniel RosenbergThis switches f2fs over to the generic support provided in the previous patch.
Since casefolded dentries behave the same in ext4 and f2fs, we decrease the maintenance burden by unifying them, and any optimizations will immediately apply to both.
--- fs/f2fs/dir.c | 84 +++++------------------------------------ fs/f2fs/f2fs.h | 4 -- fs/f2fs/super.c | 10 ++--- fs/f2fs/sysfs.c | 10 +++-- include/linux/f2fs_fs.h | 3 -- 5 files changed, 20 insertions(+), 91 deletions(-)
fs/f2fs/dir.c +9 -75
@@ -75,21 +75,22 @@ int f2fs_init_casefolded_name(const struct inode *dir, struct f2fs_filename *fname) {#ifdef CONFIG_UNICODE -struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb); +struct super_block *sb = dir->i_sb; +struct f2fs_sb_info *sbi =F2FS_SB (sb);if (IS_CASEFOLDED (dir)) { fname->cf_name.name =f2fs_kmalloc (sbi,F2FS_NAME_LEN ,GFP_NOFS );if (!fname->cf_name.name)return -ENOMEM ; - fname->cf_name.len =utf8_casefold (sbi->s_encoding, + fname->cf_name.len =utf8_casefold (sb->s_encoding, fname->usr_fname, fname->cf_name.name,F2FS_NAME_LEN );if ((int )fname->cf_name.len <=0 ) {kfree (fname->cf_name.name); fname->cf_name.name =NULL ; -if (f2fs_has_strict_mode (sbi)) +if (sb_has_strict_encoding (sb))return -EINVAL ;/* fall back to treating name as opaque byte sequence */ }
@@ -215,8 +216,8 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,static bool f2fs_match_ci_name (const struct inode *dir,const struct qstr *name,const u8 *de_name,u32 de_name_len) { -const struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb); -const struct unicode_map *um = sbi->s_encoding; +const struct super_block *sb = dir->i_sb; +const struct unicode_map *um = sb->s_encoding;struct qstr entry =QSTR_INIT (de_name, de_name_len);int res;
@@ -226,7 +227,7 @@ static bool f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,* In strict mode, ignore invalid names. In non-strict mode, * fall back to treating them as opaque byte sequences. */ -if (f2fs_has_strict_mode (sbi) || name->len != entry.len) +if (sb_has_strict_encoding (sb) || name->len != entry.len)return false;return !memcmp (name->name, entry.name, name->len); }
@@ -1107,75 +1108,8 @@ const struct file_operations f2fs_dir_operations = { };#ifdef CONFIG_UNICODE -static int f2fs_d_compare (const struct dentry *dentry,unsigned int len, -const char *str,const struct qstr *name) -{ -const struct dentry *parent =READ_ONCE (dentry->d_parent); -const struct inode *dir =READ_ONCE (parent->d_inode); -const struct f2fs_sb_info *sbi =F2FS_SB (dentry->d_sb); -struct qstr entry =QSTR_INIT (str, len); -char strbuf[DNAME_INLINE_LEN ]; -int res; - -if (!dir || !IS_CASEFOLDED (dir)) - goto fallback; - -/* -* If the dentry name is stored in-line, then it may be concurrently -* modified by a rename. If this happens, the VFS will eventually retry -* the lookup, so it doesn't matter what ->d_compare() returns. -* However, it's unsafe to call utf8_strncasecmp() with an unstable -* string. Therefore, we have to copy the name into a temporary buffer. -*/ -if (len <=DNAME_INLINE_LEN -1 ) { -memcpy (strbuf, str, len); - strbuf[len] =0 ; - entry.name = strbuf; -/* prevent compiler from optimizing out the temporary buffer */ -barrier (); - } - - res =utf8_strncasecmp (sbi->s_encoding, name, &entry); -if (res >=0 ) -return res; - -if (f2fs_has_strict_mode (sbi)) -return -EINVAL ; -fallback: -if (len != name->len) -return 1 ; -return !!memcmp (str, name->name, len); -} - -static int f2fs_d_hash (const struct dentry *dentry,struct qstr *str) -{ -struct f2fs_sb_info *sbi =F2FS_SB (dentry->d_sb); -const struct unicode_map *um = sbi->s_encoding; -const struct inode *inode =READ_ONCE (dentry->d_inode); -unsigned char *norm; -int len, ret =0 ; - -if (!inode || !IS_CASEFOLDED (inode)) -return 0 ; - - norm =f2fs_kmalloc (sbi,PATH_MAX ,GFP_ATOMIC ); -if (!norm) -return -ENOMEM ; - - len =utf8_casefold (um, str, norm,PATH_MAX ); -if (len <0 ) { -if (f2fs_has_strict_mode (sbi)) - ret = -EINVAL ; - goto out; - } - str->hash =full_name_hash (dentry, norm, len); -out: -kvfree (norm); -return ret; -} -const struct dentry_operations f2fs_dentry_ops = { - .d_hash = f2fs_d_hash, - .d_compare = f2fs_d_compare, + .d_hash = generic_ci_d_hash, + .d_compare = generic_ci_d_compare, };#endif
fs/f2fs/f2fs.h +0 -4
@@ -1402,10 +1402,6 @@ struct f2fs_sb_info {int valid_super_block;/* valid super block no */ unsigned long s_flag;/* flags for sbi */ struct mutex writepages;/* mutex for writepages() */ -#ifdef CONFIG_UNICODE -struct unicode_map *s_encoding; -__u16 s_encoding_flags; -#endif #ifdef CONFIG_BLK_DEV_ZONED unsigned int blocks_per_blkz;/* F2FS blocks per zone */
fs/f2fs/super.c +5 -5
@@ -1257,7 +1257,7 @@ static void f2fs_put_super(struct super_block *sb)for (i =0 ; i <NR_PAGE_TYPE ; i++)kvfree (sbi->write_io[i]);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif kvfree (sbi); }
@@ -3278,7 +3278,7 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)static int f2fs_setup_casefold (struct f2fs_sb_info *sbi) {#ifdef CONFIG_UNICODE -if (f2fs_sb_has_casefold (sbi) && !sbi->s_encoding) { +if (f2fs_sb_has_casefold (sbi) && !sbi->sb->s_encoding) {const struct f2fs_sb_encodings *encoding_info;struct unicode_map *encoding;__u16 encoding_flags;
@@ -3309,8 +3309,8 @@ static int f2fs_setup_casefold(struct f2fs_sb_info *sbi)"%s-%s with flags 0x%hx" , encoding_info->name, encoding_info->version?:"\b", encoding_flags); - sbi->s_encoding = encoding; - sbi->s_encoding_flags = encoding_flags; + sbi->sb->s_encoding = encoding; + sbi->sb->s_encoding_flags = encoding_flags; sbi->sb->s_d_op = &f2fs_dentry_ops; }#else
@@ -3806,7 +3806,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)kvfree (sbi->write_io[i]);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif free_options: #ifdef CONFIG_QUOTA
fs/f2fs/sysfs.c +6 -4
@@ -176,12 +176,14 @@ static ssize_t encoding_show(struct f2fs_attr *a, struct f2fs_sb_info *sbi, char *buf) { #ifdef CONFIG_UNICODE + struct super_block *sb = sbi->sb; +if (f2fs_sb_has_casefold (sbi))return snprintf (buf,PAGE_SIZE ,"%s (%d.%d.%d)\n" , - sbi->s_encoding->charset, - (sbi->s_encoding->version >>16 ) &0xff , - (sbi->s_encoding->version >>8 ) &0xff , - sbi->s_encoding->version & 0xff); + sb->s_encoding->charset, + (sb->s_encoding->version >>16 ) &0xff , + (sb->s_encoding->version >>8 ) &0xff , + sb->s_encoding->version &0xff );#endif return sprintf (buf,"(none)" ); }
include/linux/f2fs_fs.h +0 -3
@@ -38,9 +38,6 @@#define F2FS_MAX_QUOTAS 3#define F2FS_ENC_UTF8_12_1 1 -#define F2FS_ENC_STRICT_MODE_FL (1 << 0) -#define f2fs_has_strict_mode (sbi) \ - (sbi->s_encoding_flags & F2FS_ENC_STRICT_MODE_FL)#define F2FS_IO_SIZE (sbi) (1 << F2FS_OPTION(sbi).write_io_size_bits)/* Blocks */ #define F2FS_IO_SIZE_KB (sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 2))/* KB */
Signature · 1 line
2.27.0.383.g050319c2ae-goog
Re: [PATCH v12 3/4] f2fs: Use generic casefolding support
Quoted 9 lines · Daniel Rosenberg
This switches f2fs over to the generic support provided in the previous patch.
Since casefolded dentries behave the same in ext4 and f2fs, we decrease the maintenance burden by unifying them, and any optimizations will immediately apply to both.
Signed-off-by Daniel Rosenberg <[email protected]>Reviewed-by Eric Biggers <[email protected]>
Quoted 232 lines
--- fs/f2fs/dir.c | 84 +++++------------------------------------ fs/f2fs/f2fs.h | 4 -- fs/f2fs/super.c | 10 ++--- fs/f2fs/sysfs.c | 10 +++-- include/linux/f2fs_fs.h | 3 -- 5 files changed, 20 insertions(+), 91 deletions(-)fs/f2fs/dir.c +9
-75@@ -75,21 +75,22 @@ int f2fs_init_casefolded_name(const struct inode *dir, struct f2fs_filename *fname) {#ifdef CONFIG_UNICODE -struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb); +struct super_block *sb = dir->i_sb; +struct f2fs_sb_info *sbi =F2FS_SB (sb);if (IS_CASEFOLDED (dir)) { fname->cf_name.name =f2fs_kmalloc (sbi,F2FS_NAME_LEN ,GFP_NOFS );if (!fname->cf_name.name)return -ENOMEM ; - fname->cf_name.len =utf8_casefold (sbi->s_encoding, + fname->cf_name.len =utf8_casefold (sb->s_encoding, fname->usr_fname, fname->cf_name.name,F2FS_NAME_LEN );if ((int )fname->cf_name.len <=0 ) {kfree (fname->cf_name.name); fname->cf_name.name =NULL ; -if (f2fs_has_strict_mode (sbi)) +if (sb_has_strict_encoding (sb))return -EINVAL ;/* fall back to treating name as opaque byte sequence */ }@@ -215,8 +216,8 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,static bool f2fs_match_ci_name (const struct inode *dir,const struct qstr *name,const u8 *de_name,u32 de_name_len) { -const struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb); -const struct unicode_map *um = sbi->s_encoding; +const struct super_block *sb = dir->i_sb; +const struct unicode_map *um = sb->s_encoding;struct qstr entry =QSTR_INIT (de_name, de_name_len);int res;@@ -226,7 +227,7 @@ static bool f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,* In strict mode, ignore invalid names. In non-strict mode, * fall back to treating them as opaque byte sequences. */ -if (f2fs_has_strict_mode (sbi) || name->len != entry.len) +if (sb_has_strict_encoding (sb) || name->len != entry.len)return false;return !memcmp (name->name, entry.name, name->len); }@@ -1107,75 +1108,8 @@ const struct file_operations f2fs_dir_operations = { };#ifdef CONFIG_UNICODE -static int f2fs_d_compare (const struct dentry *dentry,unsigned int len, -const char *str,const struct qstr *name) -{ -const struct dentry *parent =READ_ONCE (dentry->d_parent); -const struct inode *dir =READ_ONCE (parent->d_inode); -const struct f2fs_sb_info *sbi =F2FS_SB (dentry->d_sb); -struct qstr entry =QSTR_INIT (str, len); -char strbuf[DNAME_INLINE_LEN ]; -int res; - -if (!dir || !IS_CASEFOLDED (dir)) - goto fallback; - -/* -* If the dentry name is stored in-line, then it may be concurrently -* modified by a rename. If this happens, the VFS will eventually retry -* the lookup, so it doesn't matter what ->d_compare() returns. -* However, it's unsafe to call utf8_strncasecmp() with an unstable -* string. Therefore, we have to copy the name into a temporary buffer. -*/ -if (len <=DNAME_INLINE_LEN -1 ) { -memcpy (strbuf, str, len); - strbuf[len] =0 ; - entry.name = strbuf; -/* prevent compiler from optimizing out the temporary buffer */ -barrier (); - } - - res =utf8_strncasecmp (sbi->s_encoding, name, &entry); -if (res >=0 ) -return res; - -if (f2fs_has_strict_mode (sbi)) -return -EINVAL ; -fallback: -if (len != name->len) -return 1 ; -return !!memcmp (str, name->name, len); -} - -static int f2fs_d_hash (const struct dentry *dentry,struct qstr *str) -{ -struct f2fs_sb_info *sbi =F2FS_SB (dentry->d_sb); -const struct unicode_map *um = sbi->s_encoding; -const struct inode *inode =READ_ONCE (dentry->d_inode); -unsigned char *norm; -int len, ret =0 ; - -if (!inode || !IS_CASEFOLDED (inode)) -return 0 ; - - norm =f2fs_kmalloc (sbi,PATH_MAX ,GFP_ATOMIC ); -if (!norm) -return -ENOMEM ; - - len =utf8_casefold (um, str, norm,PATH_MAX ); -if (len <0 ) { -if (f2fs_has_strict_mode (sbi)) - ret = -EINVAL ; - goto out; - } - str->hash =full_name_hash (dentry, norm, len); -out: -kvfree (norm); -return ret; -} -const struct dentry_operations f2fs_dentry_ops = { - .d_hash = f2fs_d_hash, - .d_compare = f2fs_d_compare, + .d_hash = generic_ci_d_hash, + .d_compare = generic_ci_d_compare, };#endif fs/f2fs/f2fs.h +0
-4@@ -1402,10 +1402,6 @@ struct f2fs_sb_info {int valid_super_block;/* valid super block no */ unsigned long s_flag;/* flags for sbi */ struct mutex writepages;/* mutex for writepages() */ -#ifdef CONFIG_UNICODE -struct unicode_map *s_encoding; -__u16 s_encoding_flags; -#endif #ifdef CONFIG_BLK_DEV_ZONED unsigned int blocks_per_blkz;/* F2FS blocks per zone */ fs/f2fs/super.c +5
-5@@ -1257,7 +1257,7 @@ static void f2fs_put_super(struct super_block *sb)for (i =0 ; i <NR_PAGE_TYPE ; i++)kvfree (sbi->write_io[i]);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif kvfree (sbi); }@@ -3278,7 +3278,7 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)static int f2fs_setup_casefold (struct f2fs_sb_info *sbi) {#ifdef CONFIG_UNICODE -if (f2fs_sb_has_casefold (sbi) && !sbi->s_encoding) { +if (f2fs_sb_has_casefold (sbi) && !sbi->sb->s_encoding) {const struct f2fs_sb_encodings *encoding_info;struct unicode_map *encoding;__u16 encoding_flags;@@ -3309,8 +3309,8 @@ static int f2fs_setup_casefold(struct f2fs_sb_info *sbi)"%s-%s with flags 0x%hx" , encoding_info->name, encoding_info->version?:"\b", encoding_flags); - sbi->s_encoding = encoding; - sbi->s_encoding_flags = encoding_flags; + sbi->sb->s_encoding = encoding; + sbi->sb->s_encoding_flags = encoding_flags; sbi->sb->s_d_op = &f2fs_dentry_ops; }#else @@ -3806,7 +3806,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)kvfree (sbi->write_io[i]);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif free_options: #ifdef CONFIG_QUOTAfs/f2fs/sysfs.c +6
-4@@ -176,12 +176,14 @@ static ssize_t encoding_show(struct f2fs_attr *a, struct f2fs_sb_info *sbi, char *buf) { #ifdef CONFIG_UNICODE + struct super_block *sb = sbi->sb; +if (f2fs_sb_has_casefold (sbi))return snprintf (buf,PAGE_SIZE ,"%s (%d.%d.%d)\n" , - sbi->s_encoding->charset, - (sbi->s_encoding->version >>16 ) &0xff , - (sbi->s_encoding->version >>8 ) &0xff , - sbi->s_encoding->version & 0xff); + sb->s_encoding->charset, + (sb->s_encoding->version >>16 ) &0xff , + (sb->s_encoding->version >>8 ) &0xff , + sb->s_encoding->version &0xff );#endif return sprintf (buf,"(none)" ); }include/linux/f2fs_fs.h +0
-3@@ -38,9 +38,6 @@#define F2FS_MAX_QUOTAS 3#define F2FS_ENC_UTF8_12_1 1 -#define F2FS_ENC_STRICT_MODE_FL (1 << 0) -#define f2fs_has_strict_mode (sbi) \ - (sbi->s_encoding_flags & F2FS_ENC_STRICT_MODE_FL)#define F2FS_IO_SIZE (sbi) (1 << F2FS_OPTION(sbi).write_io_size_bits)/* Blocks */ #define F2FS_IO_SIZE_KB (sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 2))/* KB */ Signature · 1 line
2.27.0.383.g050319c2ae-goog
PATCH v12 4/4 ext4: Use generic casefolding support
In reply to Daniel RosenbergThis switches ext4 over to the generic support provided in the previous patch.
Since casefolded dentries behave the same in ext4 and f2fs, we decrease the maintenance burden by unifying them, and any optimizations will immediately apply to both.
--- fs/ext4/dir.c | 64 ++----------------------------------------------- fs/ext4/ext4.h | 12 ---------- fs/ext4/hash.c | 2 +- fs/ext4/namei.c | 20 +++++++--------- fs/ext4/super.c | 12 +++++----- 5 files changed, 17 insertions(+), 93 deletions(-)
fs/ext4/dir.c +2 -62
@@ -669,68 +669,8 @@ const struct file_operations ext4_dir_operations = { };#ifdef CONFIG_UNICODE -static int ext4_d_compare (const struct dentry *dentry,unsigned int len, -const char *str,const struct qstr *name) -{ -struct qstr qstr = {.name = str, .len = len }; -const struct dentry *parent =READ_ONCE (dentry->d_parent); -const struct inode *inode =READ_ONCE (parent->d_inode); -char strbuf[DNAME_INLINE_LEN ]; - -if (!inode || !IS_CASEFOLDED (inode) || - !EXT4_SB (inode->i_sb)->s_encoding) { -if (len != name->len) -return -1 ; -return memcmp (str, name->name, len); - } - -/* -* If the dentry name is stored in-line, then it may be concurrently -* modified by a rename. If this happens, the VFS will eventually retry -* the lookup, so it doesn't matter what ->d_compare() returns. -* However, it's unsafe to call utf8_strncasecmp() with an unstable -* string. Therefore, we have to copy the name into a temporary buffer. -*/ -if (len <=DNAME_INLINE_LEN -1 ) { -memcpy (strbuf, str, len); - strbuf[len] =0 ; - qstr.name = strbuf; -/* prevent compiler from optimizing out the temporary buffer */ -barrier (); - } - -return ext4_ci_compare (inode, name, &qstr, false); -} - -static int ext4_d_hash (const struct dentry *dentry,struct qstr *str) -{ -const struct ext4_sb_info *sbi =EXT4_SB (dentry->d_sb); -const struct unicode_map *um = sbi->s_encoding; -const struct inode *inode =READ_ONCE (dentry->d_inode); -unsigned char *norm; -int len, ret =0 ; - -if (!inode || !IS_CASEFOLDED (inode) || !um) -return 0 ; - - norm =kmalloc (PATH_MAX ,GFP_ATOMIC ); -if (!norm) -return -ENOMEM ; - - len =utf8_casefold (um, str, norm,PATH_MAX ); -if (len <0 ) { -if (ext4_has_strict_mode (sbi)) - ret = -EINVAL ; - goto out; - } - str->hash =full_name_hash (dentry, norm, len); -out: -kfree (norm); -return ret; -} -const struct dentry_operations ext4_dentry_ops = { - .d_hash = ext4_d_hash, - .d_compare = ext4_d_compare, + .d_hash = generic_ci_d_hash, + .d_compare = generic_ci_d_compare, };#endif
fs/ext4/ext4.h +0 -12
@@ -1393,14 +1393,6 @@ struct ext4_super_block {#define EXT4_ENC_UTF8_12_1 1 -/* -* Flags for ext4_sb_info.s_encoding_flags. -*/ -#define EXT4_ENC_STRICT_MODE_FL (1 << 0) - -#define ext4_has_strict_mode (sbi) \ - (sbi->s_encoding_flags & EXT4_ENC_STRICT_MODE_FL) -/* * fourth extended-fs super-block data in memory */
@@ -1450,10 +1442,6 @@ struct ext4_sb_info {struct kobject s_kobj;struct completion s_kobj_unregister;struct super_block *s_sb; -#ifdef CONFIG_UNICODE -struct unicode_map *s_encoding; -__u16 s_encoding_flags; -#endif /* Journaling */ struct journal_s *s_journal;
fs/ext4/hash.c +1 -1
@@ -275,7 +275,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len, struct dx_hash_info *hinfo) {#ifdef CONFIG_UNICODE -const struct unicode_map *um =EXT4_SB (dir->i_sb)->s_encoding; +const struct unicode_map *um = dir->i_sb->s_encoding;int r, dlen;unsigned char *buff;struct qstr qstr = {.name = name, .len = len };
fs/ext4/namei.c +8 -12
@@ -1286,8 +1286,8 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)int ext4_ci_compare (const struct inode *parent,const struct qstr *name,const struct qstr *entry,bool quick) { -const struct ext4_sb_info *sbi =EXT4_SB (parent->i_sb); -const struct unicode_map *um = sbi->s_encoding; +const struct super_block *sb = parent->i_sb; +const struct unicode_map *um = sb->s_encoding;int ret;if (quick)
@@ -1299,7 +1299,7 @@ int ext4_ci_compare(const struct inode *parent, const struct qstr *name,/* Handle invalid character sequence as either an error * or as an opaque byte sequence. */ -if (ext4_has_strict_mode (sbi)) +if (sb_has_strict_encoding (sb))return -EINVAL ;if (name->len != entry->len)
@@ -1316,7 +1316,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, {int len; -if (!IS_CASEFOLDED (dir) || !EXT4_SB (dir->i_sb)->s_encoding) { +if (!IS_CASEFOLDED (dir) || !dir->i_sb->s_encoding) { cf_name->name =NULL ;return ; }
@@ -1325,7 +1325,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,if (!cf_name->name)return ; - len =utf8_casefold (EXT4_SB (dir->i_sb)->s_encoding, + len =utf8_casefold (dir->i_sb->s_encoding, iname, cf_name->name,EXT4_NAME_LEN );if (len <=0 ) {
@@ -1362,7 +1362,7 @@ static inline bool ext4_match(const struct inode *parent,#endif #ifdef CONFIG_UNICODE -if (EXT4_SB (parent->i_sb)->s_encoding &&IS_CASEFOLDED (parent)) { +if (parent->i_sb->s_encoding &&IS_CASEFOLDED (parent)) {if (fname->cf_name.name) {struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len};
@@ -2171,9 +2171,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,struct buffer_head *bh =NULL ;struct ext4_dir_entry_2 *de;struct super_block *sb; -#ifdef CONFIG_UNICODE -struct ext4_sb_info *sbi; -#endif struct ext4_filename fname;int retval;int dx_fallback=0 ;
@@ -2190,9 +2187,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,return -EINVAL ;#ifdef CONFIG_UNICODE - sbi =EXT4_SB (sb); -if (ext4_has_strict_mode (sbi) &&IS_CASEFOLDED (dir) && - sbi->s_encoding &&utf8_validate (sbi->s_encoding, &dentry->d_name)) +if (sb_has_strict_encoding (sb) &&IS_CASEFOLDED (dir) && + sb->s_encoding &&utf8_validate (sb->s_encoding, &dentry->d_name))return -EINVAL ;#endif
fs/ext4/super.c +6 -6
@@ -1102,7 +1102,7 @@ static void ext4_put_super(struct super_block *sb)fs_put_dax (sbi->s_daxdev);fscrypt_free_dummy_context (&sbi->s_dummy_enc_ctx);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif kfree (sbi); }
@@ -4035,7 +4035,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount;#ifdef CONFIG_UNICODE -if (ext4_has_feature_casefold (sb) && !sbi->s_encoding) { +if (ext4_has_feature_casefold (sb) && !sb->s_encoding) {const struct ext4_sb_encodings *encoding_info;struct unicode_map *encoding;__u16 encoding_flags;
@@ -4066,8 +4066,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)"%s-%s with flags 0x%hx" , encoding_info->name, encoding_info->version?:"\b", encoding_flags); - sbi->s_encoding = encoding; - sbi->s_encoding_flags = encoding_flags; + sb->s_encoding = encoding; + sb->s_encoding_flags = encoding_flags; }#endif
@@ -4678,7 +4678,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) }#ifdef CONFIG_UNICODE -if (sbi->s_encoding) +if (sb->s_encoding) sb->s_d_op = &ext4_dentry_ops;#endif
@@ -4873,7 +4873,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)crypto_free_shash (sbi->s_chksum_driver);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif #ifdef CONFIG_QUOTA
Signature · 1 line
2.27.0.383.g050319c2ae-goog
Re: [PATCH v12 4/4] ext4: Use generic casefolding support
Quoted 27 lines · Daniel Rosenberg
This switches ext4 over to the generic support provided in the previous patch.
Since casefolded dentries behave the same in ext4 and f2fs, we decrease the maintenance burden by unifying them, and any optimizations will immediately apply to both.
Signed-off-by Daniel Rosenberg <[email protected]>Reviewed-by Eric Biggers <[email protected]>#ifdef
CONFIG_UNICODEfs/ext4/namei.c +1
-4-if (EXT4_SB (parent->i_sb)->s_encoding &&IS_CASEFOLDED (parent)) { +if (parent->i_sb->s_encoding &&IS_CASEFOLDED (parent)) {if (fname->cf_name.name) {struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len};@@ -2171,9 +2171,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,struct buffer_head *bh =NULL ;struct ext4_dir_entry_2 *de;struct super_block *sb; -#ifdef CONFIG_UNICODE -struct ext4_sb_info *sbi; -#endif struct ext4_filename fname;int retval;int dx_fallback=0 ;
fs/ext4/namei.c static int ext4_add_entry(handle_t *handle, struct dentry *dentry, · line 2192
Quoted 9 lines
fs/ext4/namei.c +2
-3@@ -2190,9 +2187,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,return -EINVAL ;#ifdef CONFIG_UNICODE - sbi =EXT4_SB (sb); -if (ext4_has_strict_mode (sbi) &&IS_CASEFOLDED (dir) && - sbi->s_encoding &&utf8_validate (sbi->s_encoding, &dentry->d_name)) +if (sb_has_strict_encoding (sb) &&IS_CASEFOLDED (dir) && + sb->s_encoding &&utf8_validate (sb->s_encoding, &dentry->d_name))return -EINVAL ;
hm, just noticed the sb->s_encoding check here is superfluous, since the has_strict_mode() cannot be true if !s_encoding. Not related to this patch though.
Daniel, are you still working on getting this upstream? The fscrypt support would be very useful for us. :)
In the hope this will get upstream, as its been flying for a while and looks correct.
Signature · 1 line
Gabriel Krisman Bertazi
Eric Biggers
maintainerRe: [PATCH v12 4/4] ext4: Use generic casefolding support
Quoted 43 lines · Gabriel Krisman Bertazi
Quoted 27 lines · Daniel Rosenberg
This switches ext4 over to the generic support provided in the previous patch.
Since casefolded dentries behave the same in ext4 and f2fs, we decrease the maintenance burden by unifying them, and any optimizations will immediately apply to both.
Signed-off-by Daniel Rosenberg <[email protected]>Reviewed-by Eric Biggers <[email protected]>#ifdef
CONFIG_UNICODEfs/ext4/namei.c +1
-4-if (EXT4_SB (parent->i_sb)->s_encoding &&IS_CASEFOLDED (parent)) { +if (parent->i_sb->s_encoding &&IS_CASEFOLDED (parent)) {if (fname->cf_name.name) {struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len};@@ -2171,9 +2171,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,struct buffer_head *bh =NULL ;struct ext4_dir_entry_2 *de;struct super_block *sb; -#ifdef CONFIG_UNICODE -struct ext4_sb_info *sbi; -#endif struct ext4_filename fname;int retval;int dx_fallback=0 ;fs/ext4/namei.c static int ext4_add_entry(handle_t *handle, struct dentry *dentry, · line 2192
Quoted 9 lines
fs/ext4/namei.c +2
-3@@ -2190,9 +2187,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,return -EINVAL ;#ifdef CONFIG_UNICODE - sbi =EXT4_SB (sb); -if (ext4_has_strict_mode (sbi) &&IS_CASEFOLDED (dir) && - sbi->s_encoding &&utf8_validate (sbi->s_encoding, &dentry->d_name)) +if (sb_has_strict_encoding (sb) &&IS_CASEFOLDED (dir) && + sb->s_encoding &&utf8_validate (sb->s_encoding, &dentry->d_name))return -EINVAL ;hm, just noticed the
sb->s_encodingcheck here is superfluous, since thehas_strict_mode()cannot be true if !s_encoding. Not related to this patch though.
Quoted 7 lines
Daniel, are you still working on getting this upstream? The fscrypt support would be very useful for us. :)
In the hope this will get upstream, as its been flying for a while and looks correct.
Reviewed-by Gabriel Krisman Bertazi <[email protected]>
We couldn't get a response from Ted, so instead Jaegeuk has applied patches 1-3 to f2fs/dev for 5.10. Hopefully Ted will take the ext4 patch for 5.11.
I believe that Daniel is planning to resend the actual encryption+casefolding support soon, but initially only for f2fs since that will be ready first.
- Eric
Re: [PATCH v12 4/4] ext4: Use generic casefolding support
Quoted 53 lines · Eric Biggers
Quoted 43 lines · Gabriel Krisman Bertazi
Quoted 27 lines · Daniel Rosenberg
This switches ext4 over to the generic support provided in the previous patch.
Since casefolded dentries behave the same in ext4 and f2fs, we decrease the maintenance burden by unifying them, and any optimizations will immediately apply to both.
Signed-off-by Daniel Rosenberg <[email protected]>Reviewed-by Eric Biggers <[email protected]>#ifdef
CONFIG_UNICODEfs/ext4/namei.c +1
-4-if (EXT4_SB (parent->i_sb)->s_encoding &&IS_CASEFOLDED (parent)) { +if (parent->i_sb->s_encoding &&IS_CASEFOLDED (parent)) {if (fname->cf_name.name) {struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len};@@ -2171,9 +2171,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,struct buffer_head *bh =NULL ;struct ext4_dir_entry_2 *de;struct super_block *sb; -#ifdef CONFIG_UNICODE -struct ext4_sb_info *sbi; -#endif struct ext4_filename fname;int retval;int dx_fallback=0 ;fs/ext4/namei.c static int ext4_add_entry(handle_t *handle, struct dentry *dentry, · line 2192
Quoted 9 lines
fs/ext4/namei.c +2
-3@@ -2190,9 +2187,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,return -EINVAL ;#ifdef CONFIG_UNICODE - sbi =EXT4_SB (sb); -if (ext4_has_strict_mode (sbi) &&IS_CASEFOLDED (dir) && - sbi->s_encoding &&utf8_validate (sbi->s_encoding, &dentry->d_name)) +if (sb_has_strict_encoding (sb) &&IS_CASEFOLDED (dir) && + sb->s_encoding &&utf8_validate (sb->s_encoding, &dentry->d_name))return -EINVAL ;hm, just noticed the
sb->s_encodingcheck here is superfluous, since thehas_strict_mode()cannot be true if !s_encoding. Not related to this patch though.Quoted 7 lines
Daniel, are you still working on getting this upstream? The fscrypt support would be very useful for us. :)
In the hope this will get upstream, as its been flying for a while and looks correct.
Reviewed-by Gabriel Krisman Bertazi <[email protected]>
Quoted 7 lines
We couldn't get a response from Ted, so instead Jaegeuk has applied patches 1-3 to f2fs/dev for 5.10. Hopefully Ted will take the ext4 patch for 5.11.
I believe that Daniel is planning to resend the actual encryption+casefolding support soon, but initially only for f2fs since that will be ready first.
- Eric
Yes, planning to send them shortly. Just checking that I've not missed anything. For the sb_has_strict_encoding, I don't think that's actually checking s_encoding, though it does check s_encoding_flags. I'm planning to resend this one with that set, since it's not queued in the f2fs tree.
-Daniel
Eric Biggers
maintainerQuoted 8 lines · Daniel Rosenberg
This lays the ground work for enabling casefolding and encryption at the same time for ext4 and f2fs. A future set of patches will enable that functionality.
These unify the highly similar
dentry_operationsthat ext4 and f2fs both use for casefolding. In addition, they improved_hashby not requiring a new string allocation.
Quoted 6 lines
Daniel Rosenberg (4):
unicode: Addutf8_casefold_hash
fs: Add standard casefolding support
f2fs: Use generic casefolding support
ext4: Use generic casefolding support
Ted, are you interested in taking this through the ext4 tree for 5.9?
- Eric
Eric Biggers
maintainerQuoted 16 lines · Eric Biggers
Quoted 8 lines · Daniel Rosenberg
This lays the ground work for enabling casefolding and encryption at the same time for ext4 and f2fs. A future set of patches will enable that functionality.
These unify the highly similar
dentry_operationsthat ext4 and f2fs both use for casefolding. In addition, they improved_hashby not requiring a new string allocation.Quoted 6 lines
Daniel Rosenberg (4):
unicode: Addutf8_casefold_hash
fs: Add standard casefolding support
f2fs: Use generic casefolding support
ext4: Use generic casefolding support
Quoted 3 lines
Ted, are you interested in taking this through the ext4 tree for 5.9?
- Eric
Ping?
Eric Biggers
maintainerQuoted 17 lines · Eric Biggers
Quoted 16 lines · Eric Biggers
Quoted 14 lines · Daniel Rosenberg
This lays the ground work for enabling casefolding and encryption at the same time for ext4 and f2fs. A future set of patches will enable that functionality.
These unify the highly similar
dentry_operationsthat ext4 and f2fs both use for casefolding. In addition, they improved_hashby not requiring a new string allocation.Daniel Rosenberg (4):
unicode: Addutf8_casefold_hash
fs: Add standard casefolding support
f2fs: Use generic casefolding support
ext4: Use generic casefolding support
Quoted 6 lines
Quoted 3 lines
Ted, are you interested in taking this through the ext4 tree for 5.9?
- Eric
Ping?
Unfortunately this patchset got ignored for 5.9.
Ted, will you have any interest in taking this patchset for 5.10? Or should Jaegeuk just take patches 1-3 via the f2fs tree?
The fscrypt tree is also an option, but I feel it's not really appropriate since this patchset is just a refactoring of the existing casefolding support.
More reviews on patches 1-2 would be appreciated too. So far just Gabriel and I have reviewed them. I was hoping that other people would review them too.
- Eric
Jaegeuk Kim
maintainerQuoted 22 lines · Eric Biggers
Quoted 21 lines · Eric Biggers
Quoted 19 lines · Eric Biggers
Quoted 8 lines · Daniel Rosenberg
This lays the ground work for enabling casefolding and encryption at the same time for ext4 and f2fs. A future set of patches will enable that functionality.
These unify the highly similar
dentry_operationsthat ext4 and f2fs both use for casefolding. In addition, they improved_hashby not requiring a new string allocation.Quoted 6 lines
Daniel Rosenberg (4):
unicode: Addutf8_casefold_hash
fs: Add standard casefolding support
f2fs: Use generic casefolding support
ext4: Use generic casefolding supportTed, are you interested in taking this through the ext4 tree for 5.9?
- Eric
Quoted 7 lines
Quoted 2 lines
Ping?
Unfortunately this patchset got ignored for 5.9.
Ted, will you have any interest in taking this patchset for 5.10? Or should Jaegeuk just take patches 1-3 via the f2fs tree?
fyi; I think I can merge 1-3, if Al has no concern on 1 & 2.
Quoted 8 lines
The fscrypt tree is also an option, but I feel it's not really appropriate since this patchset is just a refactoring of the existing casefolding support.
More reviews on patches 1-2 would be appreciated too. So far just Gabriel and I have reviewed them. I was hoping that other people would review them too.
- Eric