diff options
-rw-r--r-- | fs/f2fs/dir.c | 125 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 18 | ||||
-rw-r--r-- | fs/f2fs/file.c | 14 | ||||
-rw-r--r-- | fs/f2fs/hash.c | 37 | ||||
-rw-r--r-- | fs/f2fs/inline.c | 4 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 4 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 21 | ||||
-rw-r--r-- | fs/f2fs/super.c | 1 |
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 | ||
84 | static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, | 85 | static 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 | */ | ||
114 | int 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 | |||
104 | struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname, | 139 | struct 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 | ||
1006 | static 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 | |||
1020 | static 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); | ||
1041 | out: | ||
1042 | kvfree(norm); | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | const 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); |
2934 | struct dentry *f2fs_get_parent(struct dentry *child); | 2937 | struct dentry *f2fs_get_parent(struct dentry *child); |
2935 | 2938 | ||
2939 | extern 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 | */ |
2999 | f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, | 3006 | f2fs_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 | ||
3442 | extern const struct file_operations f2fs_dir_operations; | 3449 | extern const struct file_operations f2fs_dir_operations; |
3450 | #ifdef CONFIG_UNICODE | ||
3451 | extern const struct dentry_operations f2fs_dentry_ops; | ||
3452 | #endif | ||
3443 | extern const struct file_operations f2fs_file_operations; | 3453 | extern const struct file_operations f2fs_file_operations; |
3444 | extern const struct inode_operations f2fs_file_inode_operations; | 3454 | extern const struct inode_operations f2fs_file_inode_operations; |
3445 | extern const struct address_space_operations f2fs_dblock_aops; | 3455 | extern 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 */ |
1726 | static inline u32 f2fs_iflags_to_fsflags(u32 iflags) | 1736 | static 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 | ||
70 | f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, | 71 | static 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 | |||
108 | f2fs_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 | |||
137 | opaque_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 | ||
54 | static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) | 56 | static 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 | } |
491 | out_splice: | 491 | out_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)) { |