summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Rosenberg <drosen@google.com>2019-07-23 19:05:29 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2019-08-23 10:57:13 -0400
commit2c2eb7a300cd7c6945dafb077801dca95d7a6c25 (patch)
tree374c6fcd603ee0c339a10d4aa76b3d2e8703a914
parent5aba54302a46fdd589040b928d5d010e5ace1234 (diff)
f2fs: Support case-insensitive file name lookups
Modeled after commit b886ee3e778e ("ext4: Support case-insensitive file name lookups") """ This patch implements the actual support for case-insensitive file name lookups in f2fs, based on the feature bit and the encoding stored in the superblock. A filesystem that has the casefold feature set is able to configure directories with the +F (F2FS_CASEFOLD_FL) attribute, enabling lookups to succeed in that directory in a case-insensitive fashion, i.e: match a directory entry even if the name used by userspace is not a byte per byte match with the disk name, but is an equivalent case-insensitive version of the Unicode string. This operation is called a case-insensitive file name lookup. The feature is configured as an inode attribute applied to directories and inherited by its children. This attribute can only be enabled on empty directories for filesystems that support the encoding feature, thus preventing collision of file names that only differ by case. * dcache handling: For a +F directory, F2Fs only stores the first equivalent name dentry used in the dcache. This is done to prevent unintentional duplication of dentries in the dcache, while also allowing the VFS code to quickly find the right entry in the cache despite which equivalent string was used in a previous lookup, without having to resort to ->lookup(). d_hash() of casefolded directories is implemented as the hash of the casefolded string, such that we always have a well-known bucket for all the equivalencies of the same string. d_compare() uses the utf8_strncasecmp() infrastructure, which handles the comparison of equivalent, same case, names as well. For now, negative lookups are not inserted in the dcache, since they would need to be invalidated anyway, because we can't trust missing file dentries. This is bad for performance but requires some leveraging of the vfs layer to fix. We can live without that for now, and so does everyone else. * on-disk data: Despite using a specific version of the name as the internal representation within the dcache, the name stored and fetched from the disk is a byte-per-byte match with what the user requested, making this implementation 'name-preserving'. i.e. no actual information is lost when writing to storage. DX is supported by modifying the hashes used in +F directories to make them case/encoding-aware. The new disk hashes are calculated as the hash of the full casefolded string, instead of the string directly. This allows us to efficiently search for file names in the htree without requiring the user to provide an exact name. * Dealing with invalid sequences: By default, when a invalid UTF-8 sequence is identified, ext4 will treat it as an opaque byte sequence, ignoring the encoding and reverting to the old behavior for that unique file. This means that case-insensitive file name lookup will not work only for that file. An optional bit can be set in the superblock telling the filesystem code and userspace tools to enforce the encoding. When that optional bit is set, any attempt to create a file name using an invalid UTF-8 sequence will fail and return an error to userspace. * Normalization algorithm: The UTF-8 algorithms used to compare strings in f2fs is implemented in fs/unicode, and is based on a previous version developed by SGI. It implements the Canonical decomposition (NFD) algorithm described by the Unicode specification 12.1, or higher, combined with the elimination of ignorable code points (NFDi) and full case-folding (CF) as documented in fs/unicode/utf8_norm.c. NFD seems to be the best normalization method for F2FS because: - It has a lower cost than NFC/NFKC (which requires decomposing to NFD as an intermediary step) - It doesn't eliminate important semantic meaning like compatibility decompositions. Although: - This implementation is not completely linguistic accurate, because different languages have conflicting rules, which would require the specialization of the filesystem to a given locale, which brings all sorts of problems for removable media and for users who use more than one language. """ Signed-off-by: Daniel Rosenberg <drosen@google.com> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/dir.c125
-rw-r--r--fs/f2fs/f2fs.h18
-rw-r--r--fs/f2fs/file.c14
-rw-r--r--fs/f2fs/hash.c37
-rw-r--r--fs/f2fs/inline.c4
-rw-r--r--fs/f2fs/inode.c4
-rw-r--r--fs/f2fs/namei.c21
-rw-r--r--fs/f2fs/super.c1
8 files changed, 204 insertions, 20 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 85a1528f319f..dac07d17cdbd 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -8,6 +8,7 @@
8#include <linux/fs.h> 8#include <linux/fs.h>
9#include <linux/f2fs_fs.h> 9#include <linux/f2fs_fs.h>
10#include <linux/sched/signal.h> 10#include <linux/sched/signal.h>
11#include <linux/unicode.h>
11#include "f2fs.h" 12#include "f2fs.h"
12#include "node.h" 13#include "node.h"
13#include "acl.h" 14#include "acl.h"
@@ -81,7 +82,8 @@ static unsigned long dir_block_index(unsigned int level,
81 return bidx; 82 return bidx;
82} 83}
83 84
84static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, 85static struct f2fs_dir_entry *find_in_block(struct inode *dir,
86 struct page *dentry_page,
85 struct fscrypt_name *fname, 87 struct fscrypt_name *fname,
86 f2fs_hash_t namehash, 88 f2fs_hash_t namehash,
87 int *max_slots, 89 int *max_slots,
@@ -93,7 +95,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
93 95
94 dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page); 96 dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);
95 97
96 make_dentry_ptr_block(NULL, &d, dentry_blk); 98 make_dentry_ptr_block(dir, &d, dentry_blk);
97 de = f2fs_find_target_dentry(fname, namehash, max_slots, &d); 99 de = f2fs_find_target_dentry(fname, namehash, max_slots, &d);
98 if (de) 100 if (de)
99 *res_page = dentry_page; 101 *res_page = dentry_page;
@@ -101,6 +103,39 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
101 return de; 103 return de;
102} 104}
103 105
106#ifdef CONFIG_UNICODE
107/*
108 * Test whether a case-insensitive directory entry matches the filename
109 * being searched for.
110 *
111 * Returns: 0 if the directory entry matches, more than 0 if it
112 * doesn't match or less than zero on error.
113 */
114int f2fs_ci_compare(const struct inode *parent, const struct qstr *name,
115 const struct qstr *entry)
116{
117 const struct f2fs_sb_info *sbi = F2FS_SB(parent->i_sb);
118 const struct unicode_map *um = sbi->s_encoding;
119 int ret;
120
121 ret = utf8_strncasecmp(um, name, entry);
122 if (ret < 0) {
123 /* Handle invalid character sequence as either an error
124 * or as an opaque byte sequence.
125 */
126 if (f2fs_has_strict_mode(sbi))
127 return -EINVAL;
128
129 if (name->len != entry->len)
130 return 1;
131
132 return !!memcmp(name->name, entry->name, name->len);
133 }
134
135 return ret;
136}
137#endif
138
104struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname, 139struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
105 f2fs_hash_t namehash, int *max_slots, 140 f2fs_hash_t namehash, int *max_slots,
106 struct f2fs_dentry_ptr *d) 141 struct f2fs_dentry_ptr *d)
@@ -108,6 +143,9 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
108 struct f2fs_dir_entry *de; 143 struct f2fs_dir_entry *de;
109 unsigned long bit_pos = 0; 144 unsigned long bit_pos = 0;
110 int max_len = 0; 145 int max_len = 0;
146#ifdef CONFIG_UNICODE
147 struct qstr entry;
148#endif
111 149
112 if (max_slots) 150 if (max_slots)
113 *max_slots = 0; 151 *max_slots = 0;
@@ -119,16 +157,28 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
119 } 157 }
120 158
121 de = &d->dentry[bit_pos]; 159 de = &d->dentry[bit_pos];
160#ifdef CONFIG_UNICODE
161 entry.name = d->filename[bit_pos];
162 entry.len = de->name_len;
163#endif
122 164
123 if (unlikely(!de->name_len)) { 165 if (unlikely(!de->name_len)) {
124 bit_pos++; 166 bit_pos++;
125 continue; 167 continue;
126 } 168 }
169 if (de->hash_code == namehash) {
170#ifdef CONFIG_UNICODE
171 if (F2FS_SB(d->inode->i_sb)->s_encoding &&
172 IS_CASEFOLDED(d->inode) &&
173 !f2fs_ci_compare(d->inode,
174 fname->usr_fname, &entry))
175 goto found;
127 176
128 if (de->hash_code == namehash && 177#endif
129 fscrypt_match_name(fname, d->filename[bit_pos], 178 if (fscrypt_match_name(fname, d->filename[bit_pos],
130 le16_to_cpu(de->name_len))) 179 le16_to_cpu(de->name_len)))
131 goto found; 180 goto found;
181 }
132 182
133 if (max_slots && max_len > *max_slots) 183 if (max_slots && max_len > *max_slots)
134 *max_slots = max_len; 184 *max_slots = max_len;
@@ -157,7 +207,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
157 struct f2fs_dir_entry *de = NULL; 207 struct f2fs_dir_entry *de = NULL;
158 bool room = false; 208 bool room = false;
159 int max_slots; 209 int max_slots;
160 f2fs_hash_t namehash = f2fs_dentry_hash(&name, fname); 210 f2fs_hash_t namehash = f2fs_dentry_hash(dir, &name, fname);
161 211
162 nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level); 212 nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
163 nblock = bucket_blocks(level); 213 nblock = bucket_blocks(level);
@@ -179,8 +229,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
179 } 229 }
180 } 230 }
181 231
182 de = find_in_block(dentry_page, fname, namehash, &max_slots, 232 de = find_in_block(dir, dentry_page, fname, namehash,
183 res_page); 233 &max_slots, res_page);
184 if (de) 234 if (de)
185 break; 235 break;
186 236
@@ -250,6 +300,14 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
250 struct fscrypt_name fname; 300 struct fscrypt_name fname;
251 int err; 301 int err;
252 302
303#ifdef CONFIG_UNICODE
304 if (f2fs_has_strict_mode(F2FS_I_SB(dir)) && IS_CASEFOLDED(dir) &&
305 utf8_validate(F2FS_I_SB(dir)->s_encoding, child)) {
306 *res_page = ERR_PTR(-EINVAL);
307 return NULL;
308 }
309#endif
310
253 err = fscrypt_setup_filename(dir, child, 1, &fname); 311 err = fscrypt_setup_filename(dir, child, 1, &fname);
254 if (err) { 312 if (err) {
255 if (err == -ENOENT) 313 if (err == -ENOENT)
@@ -504,7 +562,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
504 562
505 level = 0; 563 level = 0;
506 slots = GET_DENTRY_SLOTS(new_name->len); 564 slots = GET_DENTRY_SLOTS(new_name->len);
507 dentry_hash = f2fs_dentry_hash(new_name, NULL); 565 dentry_hash = f2fs_dentry_hash(dir, new_name, NULL);
508 566
509 current_depth = F2FS_I(dir)->i_current_depth; 567 current_depth = F2FS_I(dir)->i_current_depth;
510 if (F2FS_I(dir)->chash == dentry_hash) { 568 if (F2FS_I(dir)->chash == dentry_hash) {
@@ -943,3 +1001,50 @@ const struct file_operations f2fs_dir_operations = {
943 .compat_ioctl = f2fs_compat_ioctl, 1001 .compat_ioctl = f2fs_compat_ioctl,
944#endif 1002#endif
945}; 1003};
1004
1005#ifdef CONFIG_UNICODE
1006static int f2fs_d_compare(const struct dentry *dentry, unsigned int len,
1007 const char *str, const struct qstr *name)
1008{
1009 struct qstr qstr = {.name = str, .len = len };
1010
1011 if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
1012 if (len != name->len)
1013 return -1;
1014 return memcmp(str, name, len);
1015 }
1016
1017 return f2fs_ci_compare(dentry->d_parent->d_inode, name, &qstr);
1018}
1019
1020static int f2fs_d_hash(const struct dentry *dentry, struct qstr *str)
1021{
1022 struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
1023 const struct unicode_map *um = sbi->s_encoding;
1024 unsigned char *norm;
1025 int len, ret = 0;
1026
1027 if (!IS_CASEFOLDED(dentry->d_inode))
1028 return 0;
1029
1030 norm = f2fs_kmalloc(sbi, PATH_MAX, GFP_ATOMIC);
1031 if (!norm)
1032 return -ENOMEM;
1033
1034 len = utf8_casefold(um, str, norm, PATH_MAX);
1035 if (len < 0) {
1036 if (f2fs_has_strict_mode(sbi))
1037 ret = -EINVAL;
1038 goto out;
1039 }
1040 str->hash = full_name_hash(dentry, norm, len);
1041out:
1042 kvfree(norm);
1043 return ret;
1044}
1045
1046const struct dentry_operations f2fs_dentry_ops = {
1047 .d_hash = f2fs_d_hash,
1048 .d_compare = f2fs_d_compare,
1049};
1050#endif
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index dd69e1559839..3f57ab6c9137 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2367,13 +2367,16 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr)
2367#define F2FS_INDEX_FL 0x00001000 /* hash-indexed directory */ 2367#define F2FS_INDEX_FL 0x00001000 /* hash-indexed directory */
2368#define F2FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ 2368#define F2FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
2369#define F2FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ 2369#define F2FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
2370#define F2FS_CASEFOLD_FL 0x40000000 /* Casefolded file */
2370 2371
2371/* Flags that should be inherited by new inodes from their parent. */ 2372/* Flags that should be inherited by new inodes from their parent. */
2372#define F2FS_FL_INHERITED (F2FS_SYNC_FL | F2FS_NODUMP_FL | F2FS_NOATIME_FL | \ 2373#define F2FS_FL_INHERITED (F2FS_SYNC_FL | F2FS_NODUMP_FL | F2FS_NOATIME_FL | \
2373 F2FS_DIRSYNC_FL | F2FS_PROJINHERIT_FL) 2374 F2FS_DIRSYNC_FL | F2FS_PROJINHERIT_FL | \
2375 F2FS_CASEFOLD_FL)
2374 2376
2375/* Flags that are appropriate for regular files (all but dir-specific ones). */ 2377/* Flags that are appropriate for regular files (all but dir-specific ones). */
2376#define F2FS_REG_FLMASK (~(F2FS_DIRSYNC_FL | F2FS_PROJINHERIT_FL)) 2378#define F2FS_REG_FLMASK (~(F2FS_DIRSYNC_FL | F2FS_PROJINHERIT_FL | \
2379 F2FS_CASEFOLD_FL))
2377 2380
2378/* Flags that are appropriate for non-directories/regular files. */ 2381/* Flags that are appropriate for non-directories/regular files. */
2379#define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL) 2382#define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL)
@@ -2933,6 +2936,10 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
2933 bool hot, bool set); 2936 bool hot, bool set);
2934struct dentry *f2fs_get_parent(struct dentry *child); 2937struct dentry *f2fs_get_parent(struct dentry *child);
2935 2938
2939extern int f2fs_ci_compare(const struct inode *parent,
2940 const struct qstr *name,
2941 const struct qstr *entry);
2942
2936/* 2943/*
2937 * dir.c 2944 * dir.c
2938 */ 2945 */
@@ -2996,8 +3003,8 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
2996/* 3003/*
2997 * hash.c 3004 * hash.c
2998 */ 3005 */
2999f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, 3006f2fs_hash_t f2fs_dentry_hash(const struct inode *dir,
3000 struct fscrypt_name *fname); 3007 const struct qstr *name_info, struct fscrypt_name *fname);
3001 3008
3002/* 3009/*
3003 * node.c 3010 * node.c
@@ -3440,6 +3447,9 @@ static inline void f2fs_destroy_root_stats(void) { }
3440#endif 3447#endif
3441 3448
3442extern const struct file_operations f2fs_dir_operations; 3449extern const struct file_operations f2fs_dir_operations;
3450#ifdef CONFIG_UNICODE
3451extern const struct dentry_operations f2fs_dentry_ops;
3452#endif
3443extern const struct file_operations f2fs_file_operations; 3453extern const struct file_operations f2fs_file_operations;
3444extern const struct inode_operations f2fs_file_inode_operations; 3454extern const struct inode_operations f2fs_file_inode_operations;
3445extern const struct address_space_operations f2fs_dblock_aops; 3455extern const struct address_space_operations f2fs_dblock_aops;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index a5080bea6b0b..103636c52206 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1664,6 +1664,13 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
1664 if (IS_NOQUOTA(inode)) 1664 if (IS_NOQUOTA(inode))
1665 return -EPERM; 1665 return -EPERM;
1666 1666
1667 if ((iflags ^ fi->i_flags) & F2FS_CASEFOLD_FL) {
1668 if (!f2fs_sb_has_casefold(F2FS_I_SB(inode)))
1669 return -EOPNOTSUPP;
1670 if (!f2fs_empty_dir(inode))
1671 return -ENOTEMPTY;
1672 }
1673
1667 fi->i_flags = iflags | (fi->i_flags & ~mask); 1674 fi->i_flags = iflags | (fi->i_flags & ~mask);
1668 1675
1669 if (fi->i_flags & F2FS_PROJINHERIT_FL) 1676 if (fi->i_flags & F2FS_PROJINHERIT_FL)
@@ -1698,6 +1705,7 @@ static const struct {
1698 { F2FS_INDEX_FL, FS_INDEX_FL }, 1705 { F2FS_INDEX_FL, FS_INDEX_FL },
1699 { F2FS_DIRSYNC_FL, FS_DIRSYNC_FL }, 1706 { F2FS_DIRSYNC_FL, FS_DIRSYNC_FL },
1700 { F2FS_PROJINHERIT_FL, FS_PROJINHERIT_FL }, 1707 { F2FS_PROJINHERIT_FL, FS_PROJINHERIT_FL },
1708 { F2FS_CASEFOLD_FL, FS_CASEFOLD_FL },
1701}; 1709};
1702 1710
1703#define F2FS_GETTABLE_FS_FL ( \ 1711#define F2FS_GETTABLE_FS_FL ( \
@@ -1711,7 +1719,8 @@ static const struct {
1711 FS_PROJINHERIT_FL | \ 1719 FS_PROJINHERIT_FL | \
1712 FS_ENCRYPT_FL | \ 1720 FS_ENCRYPT_FL | \
1713 FS_INLINE_DATA_FL | \ 1721 FS_INLINE_DATA_FL | \
1714 FS_NOCOW_FL) 1722 FS_NOCOW_FL | \
1723 FS_CASEFOLD_FL)
1715 1724
1716#define F2FS_SETTABLE_FS_FL ( \ 1725#define F2FS_SETTABLE_FS_FL ( \
1717 FS_SYNC_FL | \ 1726 FS_SYNC_FL | \
@@ -1720,7 +1729,8 @@ static const struct {
1720 FS_NODUMP_FL | \ 1729 FS_NODUMP_FL | \
1721 FS_NOATIME_FL | \ 1730 FS_NOATIME_FL | \
1722 FS_DIRSYNC_FL | \ 1731 FS_DIRSYNC_FL | \
1723 FS_PROJINHERIT_FL) 1732 FS_PROJINHERIT_FL | \
1733 FS_CASEFOLD_FL)
1724 1734
1725/* Convert f2fs on-disk i_flags to FS_IOC_{GET,SET}FLAGS flags */ 1735/* Convert f2fs on-disk i_flags to FS_IOC_{GET,SET}FLAGS flags */
1726static inline u32 f2fs_iflags_to_fsflags(u32 iflags) 1736static inline u32 f2fs_iflags_to_fsflags(u32 iflags)
diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c
index cc82f142f811..5bc4dcd8fc03 100644
--- a/fs/f2fs/hash.c
+++ b/fs/f2fs/hash.c
@@ -14,6 +14,7 @@
14#include <linux/f2fs_fs.h> 14#include <linux/f2fs_fs.h>
15#include <linux/cryptohash.h> 15#include <linux/cryptohash.h>
16#include <linux/pagemap.h> 16#include <linux/pagemap.h>
17#include <linux/unicode.h>
17 18
18#include "f2fs.h" 19#include "f2fs.h"
19 20
@@ -67,7 +68,7 @@ static void str2hashbuf(const unsigned char *msg, size_t len,
67 *buf++ = pad; 68 *buf++ = pad;
68} 69}
69 70
70f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, 71static f2fs_hash_t __f2fs_dentry_hash(const struct qstr *name_info,
71 struct fscrypt_name *fname) 72 struct fscrypt_name *fname)
72{ 73{
73 __u32 hash; 74 __u32 hash;
@@ -103,3 +104,37 @@ f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info,
103 f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT); 104 f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
104 return f2fs_hash; 105 return f2fs_hash;
105} 106}
107
108f2fs_hash_t f2fs_dentry_hash(const struct inode *dir,
109 const struct qstr *name_info, struct fscrypt_name *fname)
110{
111#ifdef CONFIG_UNICODE
112 struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
113 const struct unicode_map *um = sbi->s_encoding;
114 int r, dlen;
115 unsigned char *buff;
116 struct qstr folded;
117
118 if (!name_info->len || !IS_CASEFOLDED(dir))
119 goto opaque_seq;
120
121 buff = f2fs_kzalloc(sbi, sizeof(char) * PATH_MAX, GFP_KERNEL);
122 if (!buff)
123 return -ENOMEM;
124
125 dlen = utf8_casefold(um, name_info, buff, PATH_MAX);
126 if (dlen < 0) {
127 kvfree(buff);
128 goto opaque_seq;
129 }
130 folded.name = buff;
131 folded.len = dlen;
132 r = __f2fs_dentry_hash(&folded, fname);
133
134 kvfree(buff);
135 return r;
136
137opaque_seq:
138#endif
139 return __f2fs_dentry_hash(name_info, fname);
140}
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 8c0712154fb1..78d6ebe165cd 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -320,7 +320,7 @@ struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
320 return NULL; 320 return NULL;
321 } 321 }
322 322
323 namehash = f2fs_dentry_hash(&name, fname); 323 namehash = f2fs_dentry_hash(dir, &name, fname);
324 324
325 inline_dentry = inline_data_addr(dir, ipage); 325 inline_dentry = inline_data_addr(dir, ipage);
326 326
@@ -580,7 +580,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
580 580
581 f2fs_wait_on_page_writeback(ipage, NODE, true, true); 581 f2fs_wait_on_page_writeback(ipage, NODE, true, true);
582 582
583 name_hash = f2fs_dentry_hash(new_name, NULL); 583 name_hash = f2fs_dentry_hash(dir, new_name, NULL);
584 f2fs_update_dentry(ino, mode, &d, new_name, name_hash, bit_pos); 584 f2fs_update_dentry(ino, mode, &d, new_name, name_hash, bit_pos);
585 585
586 set_page_dirty(ipage); 586 set_page_dirty(ipage);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index d1998ddf14fd..5d78f2db7a67 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -46,9 +46,11 @@ void f2fs_set_inode_flags(struct inode *inode)
46 new_fl |= S_DIRSYNC; 46 new_fl |= S_DIRSYNC;
47 if (file_is_encrypt(inode)) 47 if (file_is_encrypt(inode))
48 new_fl |= S_ENCRYPTED; 48 new_fl |= S_ENCRYPTED;
49 if (flags & F2FS_CASEFOLD_FL)
50 new_fl |= S_CASEFOLD;
49 inode_set_flags(inode, new_fl, 51 inode_set_flags(inode, new_fl,
50 S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC| 52 S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
51 S_ENCRYPTED); 53 S_ENCRYPTED|S_CASEFOLD);
52} 54}
53 55
54static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) 56static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 7560c7ed38b1..9a28c5d9b3e9 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -489,6 +489,17 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
489 goto out_iput; 489 goto out_iput;
490 } 490 }
491out_splice: 491out_splice:
492#ifdef CONFIG_UNICODE
493 if (!inode && IS_CASEFOLDED(dir)) {
494 /* Eventually we want to call d_add_ci(dentry, NULL)
495 * for negative dentries in the encoding case as
496 * well. For now, prevent the negative dentry
497 * from being cached.
498 */
499 trace_f2fs_lookup_end(dir, dentry, ino, err);
500 return NULL;
501 }
502#endif
492 new = d_splice_alias(inode, dentry); 503 new = d_splice_alias(inode, dentry);
493 err = PTR_ERR_OR_ZERO(new); 504 err = PTR_ERR_OR_ZERO(new);
494 trace_f2fs_lookup_end(dir, dentry, ino, err); 505 trace_f2fs_lookup_end(dir, dentry, ino, err);
@@ -537,6 +548,16 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
537 goto fail; 548 goto fail;
538 } 549 }
539 f2fs_delete_entry(de, page, dir, inode); 550 f2fs_delete_entry(de, page, dir, inode);
551#ifdef CONFIG_UNICODE
552 /* VFS negative dentries are incompatible with Encoding and
553 * Case-insensitiveness. Eventually we'll want avoid
554 * invalidating the dentries here, alongside with returning the
555 * negative dentries at f2fs_lookup(), when it is better
556 * supported by the VFS for the CI case.
557 */
558 if (IS_CASEFOLDED(dir))
559 d_invalidate(dentry);
560#endif
540 f2fs_unlock_op(sbi); 561 f2fs_unlock_op(sbi);
541 562
542 if (IS_DIRSYNC(dir)) 563 if (IS_DIRSYNC(dir))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 8bebee8e0186..3435c8bccf3e 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3152,6 +3152,7 @@ static int f2fs_setup_casefold(struct f2fs_sb_info *sbi)
3152 3152
3153 sbi->s_encoding = encoding; 3153 sbi->s_encoding = encoding;
3154 sbi->s_encoding_flags = encoding_flags; 3154 sbi->s_encoding_flags = encoding_flags;
3155 sbi->sb->s_d_op = &f2fs_dentry_ops;
3155 } 3156 }
3156#else 3157#else
3157 if (f2fs_sb_has_casefold(sbi)) { 3158 if (f2fs_sb_has_casefold(sbi)) {