d_revalidate to reject negative dentries is not needed, because we avoided adding those in the first place during lookup, similar to what xfs does. Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxxxxxxxxxx> --- fs/ext4/dir.c | 30 ++++++++++++++++++++++++++++++ fs/ext4/ext4.h | 1 + fs/ext4/super.c | 4 ++++ 3 files changed, 35 insertions(+) diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index e2902d394f1b..c520b9e94778 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -26,6 +26,7 @@ #include <linux/buffer_head.h> #include <linux/slab.h> #include <linux/iversion.h> +#include <linux/nls.h> #include "ext4.h" #include "xattr.h" @@ -664,3 +665,32 @@ const struct file_operations ext4_dir_operations = { .open = ext4_dir_open, .release = ext4_release_dir, }; + +static int ext4_d_compare(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct nls_table *charset = EXT4_SB(dentry->d_sb)->encoding; + size_t nlen = strlen(name->name); + + return nls_strncmp(charset, str, len, name->name, nlen); +} + +static int ext4_d_hash(const struct dentry *dentry, struct qstr *q) +{ + const struct nls_table *charset = EXT4_SB(dentry->d_sb)->encoding; + unsigned char norm[PATH_MAX]; + int len; + + len = nls_normalize(charset, q->name, q->len, norm, PATH_MAX); + if (len < 0) + return -EINVAL; + + q->hash = full_name_hash(dentry, norm, len); + + return 0; +} + +const struct dentry_operations ext4_dentry_ops = { + .d_hash = ext4_d_hash, + .d_compare = ext4_d_compare, +}; diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index fb0b70d6eb68..2a5c7712967f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2953,6 +2953,7 @@ static inline void ext4_unlock_group(struct super_block *sb, /* dir.c */ extern const struct file_operations ext4_dir_operations; +extern const struct dentry_operations ext4_dentry_ops; /* file.c */ extern const struct inode_operations ext4_file_inode_operations; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 53db9b6c7e33..f292cc5bacda 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4358,6 +4358,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) iput(root); goto failed_mount4; } + + if (sbi->encoding) + sb->s_d_op = &ext4_dentry_ops; + sb->s_root = d_make_root(root); if (!sb->s_root) { ext4_msg(sb, KERN_ERR, "get root dentry failed"); -- 2.18.0