summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabriel Krisman Bertazi <krisman@collabora.co.uk>2019-04-25 14:12:08 -0400
committerTheodore Ts'o <tytso@mit.edu>2019-04-25 14:12:08 -0400
commitb886ee3e778ec2ad43e276fd378ab492cf6819b7 (patch)
treefdf44b5a293ae51a3018de3d571dd2f139ed1066
parentc83ad55eaa91c8e85dd8cc3b7b3485fac45ef7bf (diff)
ext4: Support case-insensitive file name lookups
This patch implements the actual support for case-insensitive file name lookups in ext4, 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 (EXT4_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, Ext4 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 ext4 is implemented lives 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 EXT4 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: Gabriel Krisman Bertazi <krisman@collabora.co.uk> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/dir.c48
-rw-r--r--fs/ext4/ext4.h21
-rw-r--r--fs/ext4/hash.c34
-rw-r--r--fs/ext4/ialloc.c2
-rw-r--r--fs/ext4/inline.c2
-rw-r--r--fs/ext4/inode.c4
-rw-r--r--fs/ext4/ioctl.c18
-rw-r--r--fs/ext4/namei.c107
-rw-r--r--fs/ext4/super.c6
-rw-r--r--include/linux/fs.h2
10 files changed, 223 insertions, 21 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 0ccd51f72048..884a6e776809 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -26,6 +26,7 @@
26#include <linux/buffer_head.h> 26#include <linux/buffer_head.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/iversion.h> 28#include <linux/iversion.h>
29#include <linux/unicode.h>
29#include "ext4.h" 30#include "ext4.h"
30#include "xattr.h" 31#include "xattr.h"
31 32
@@ -660,3 +661,50 @@ const struct file_operations ext4_dir_operations = {
660 .open = ext4_dir_open, 661 .open = ext4_dir_open,
661 .release = ext4_release_dir, 662 .release = ext4_release_dir,
662}; 663};
664
665#ifdef CONFIG_UNICODE
666static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
667 const char *str, const struct qstr *name)
668{
669 struct qstr qstr = {.name = str, .len = len };
670
671 if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
672 if (len != name->len)
673 return -1;
674 return !memcmp(str, name, len);
675 }
676
677 return ext4_ci_compare(dentry->d_parent->d_inode, name, &qstr);
678}
679
680static int ext4_d_hash(const struct dentry *dentry, struct qstr *str)
681{
682 const struct ext4_sb_info *sbi = EXT4_SB(dentry->d_sb);
683 const struct unicode_map *um = sbi->s_encoding;
684 unsigned char *norm;
685 int len, ret = 0;
686
687 if (!IS_CASEFOLDED(dentry->d_inode))
688 return 0;
689
690 norm = kmalloc(PATH_MAX, GFP_ATOMIC);
691 if (!norm)
692 return -ENOMEM;
693
694 len = utf8_casefold(um, str, norm, PATH_MAX);
695 if (len < 0) {
696 if (ext4_has_strict_mode(sbi))
697 ret = -EINVAL;
698 goto out;
699 }
700 str->hash = full_name_hash(dentry, norm, len);
701out:
702 kfree(norm);
703 return ret;
704}
705
706const struct dentry_operations ext4_dentry_ops = {
707 .d_hash = ext4_d_hash,
708 .d_compare = ext4_d_compare,
709};
710#endif
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index c1504c471fef..c18ab748d20d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -399,10 +399,11 @@ struct flex_groups {
399#define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */ 399#define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */
400#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */ 400#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */
401#define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ 401#define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
402#define EXT4_CASEFOLD_FL 0x40000000 /* Casefolded file */
402#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ 403#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
403 404
404#define EXT4_FL_USER_VISIBLE 0x304BDFFF /* User visible flags */ 405#define EXT4_FL_USER_VISIBLE 0x704BDFFF /* User visible flags */
405#define EXT4_FL_USER_MODIFIABLE 0x204BC0FF /* User modifiable flags */ 406#define EXT4_FL_USER_MODIFIABLE 0x604BC0FF /* User modifiable flags */
406 407
407/* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */ 408/* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
408#define EXT4_FL_XFLAG_VISIBLE (EXT4_SYNC_FL | \ 409#define EXT4_FL_XFLAG_VISIBLE (EXT4_SYNC_FL | \
@@ -417,10 +418,10 @@ struct flex_groups {
417 EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ 418 EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
418 EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\ 419 EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
419 EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\ 420 EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\
420 EXT4_PROJINHERIT_FL) 421 EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL)
421 422
422/* Flags that are appropriate for regular files (all but dir-specific ones). */ 423/* Flags that are appropriate for regular files (all but dir-specific ones). */
423#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL)) 424#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL | EXT4_CASEFOLD_FL))
424 425
425/* Flags that are appropriate for non-directories/regular files. */ 426/* Flags that are appropriate for non-directories/regular files. */
426#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL) 427#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL)
@@ -2393,8 +2394,8 @@ extern int ext4_check_all_de(struct inode *dir, struct buffer_head *bh,
2393extern int ext4_sync_file(struct file *, loff_t, loff_t, int); 2394extern int ext4_sync_file(struct file *, loff_t, loff_t, int);
2394 2395
2395/* hash.c */ 2396/* hash.c */
2396extern int ext4fs_dirhash(const char *name, int len, struct 2397extern int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
2397 dx_hash_info *hinfo); 2398 struct dx_hash_info *hinfo);
2398 2399
2399/* ialloc.c */ 2400/* ialloc.c */
2400extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t, 2401extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t,
@@ -2990,6 +2991,10 @@ static inline void ext4_unlock_group(struct super_block *sb,
2990/* dir.c */ 2991/* dir.c */
2991extern const struct file_operations ext4_dir_operations; 2992extern const struct file_operations ext4_dir_operations;
2992 2993
2994#ifdef CONFIG_UNICODE
2995extern const struct dentry_operations ext4_dentry_ops;
2996#endif
2997
2993/* file.c */ 2998/* file.c */
2994extern const struct inode_operations ext4_file_inode_operations; 2999extern const struct inode_operations ext4_file_inode_operations;
2995extern const struct file_operations ext4_file_operations; 3000extern const struct file_operations ext4_file_operations;
@@ -3082,6 +3087,10 @@ extern void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
3082extern int ext4_handle_dirty_dirent_node(handle_t *handle, 3087extern int ext4_handle_dirty_dirent_node(handle_t *handle,
3083 struct inode *inode, 3088 struct inode *inode,
3084 struct buffer_head *bh); 3089 struct buffer_head *bh);
3090extern int ext4_ci_compare(const struct inode *parent,
3091 const struct qstr *name,
3092 const struct qstr *entry);
3093
3085#define S_SHIFT 12 3094#define S_SHIFT 12
3086static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = { 3095static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
3087 [S_IFREG >> S_SHIFT] = EXT4_FT_REG_FILE, 3096 [S_IFREG >> S_SHIFT] = EXT4_FT_REG_FILE,
diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
index 46b24da33a28..d358bfcb6b3f 100644
--- a/fs/ext4/hash.c
+++ b/fs/ext4/hash.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include <linux/fs.h> 8#include <linux/fs.h>
9#include <linux/unicode.h>
9#include <linux/compiler.h> 10#include <linux/compiler.h>
10#include <linux/bitops.h> 11#include <linux/bitops.h>
11#include "ext4.h" 12#include "ext4.h"
@@ -196,7 +197,8 @@ static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)
196 * represented, and whether or not the returned hash is 32 bits or 64 197 * represented, and whether or not the returned hash is 32 bits or 64
197 * bits. 32 bit hashes will return 0 for the minor hash. 198 * bits. 32 bit hashes will return 0 for the minor hash.
198 */ 199 */
199int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) 200static int __ext4fs_dirhash(const char *name, int len,
201 struct dx_hash_info *hinfo)
200{ 202{
201 __u32 hash; 203 __u32 hash;
202 __u32 minor_hash = 0; 204 __u32 minor_hash = 0;
@@ -268,3 +270,33 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
268 hinfo->minor_hash = minor_hash; 270 hinfo->minor_hash = minor_hash;
269 return 0; 271 return 0;
270} 272}
273
274int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
275 struct dx_hash_info *hinfo)
276{
277#ifdef CONFIG_UNICODE
278 const struct unicode_map *um = EXT4_SB(dir->i_sb)->s_encoding;
279 int r, dlen;
280 unsigned char *buff;
281 struct qstr qstr = {.name = name, .len = len };
282
283 if (len && IS_CASEFOLDED(dir)) {
284 buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
285 if (!buff)
286 return -ENOMEM;
287
288 dlen = utf8_casefold(um, &qstr, buff, PATH_MAX);
289 if (dlen < 0) {
290 kfree(buff);
291 goto opaque_seq;
292 }
293
294 r = __ext4fs_dirhash(buff, dlen, hinfo);
295
296 kfree(buff);
297 return r;
298 }
299opaque_seq:
300#endif
301 return __ext4fs_dirhash(name, len, hinfo);
302}
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index f3e17a8c84b4..764ff4c56233 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -455,7 +455,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
455 if (qstr) { 455 if (qstr) {
456 hinfo.hash_version = DX_HASH_HALF_MD4; 456 hinfo.hash_version = DX_HASH_HALF_MD4;
457 hinfo.seed = sbi->s_hash_seed; 457 hinfo.seed = sbi->s_hash_seed;
458 ext4fs_dirhash(qstr->name, qstr->len, &hinfo); 458 ext4fs_dirhash(parent, qstr->name, qstr->len, &hinfo);
459 grp = hinfo.hash; 459 grp = hinfo.hash;
460 } else 460 } else
461 grp = prandom_u32(); 461 grp = prandom_u32();
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 56f6e1782d5f..f73bc3925282 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1407,7 +1407,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
1407 } 1407 }
1408 } 1408 }
1409 1409
1410 ext4fs_dirhash(de->name, de->name_len, hinfo); 1410 ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
1411 if ((hinfo->hash < start_hash) || 1411 if ((hinfo->hash < start_hash) ||
1412 ((hinfo->hash == start_hash) && 1412 ((hinfo->hash == start_hash) &&
1413 (hinfo->minor_hash < start_minor_hash))) 1413 (hinfo->minor_hash < start_minor_hash)))
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 609c8366d029..82298c63ea6d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4742,9 +4742,11 @@ void ext4_set_inode_flags(struct inode *inode)
4742 new_fl |= S_DAX; 4742 new_fl |= S_DAX;
4743 if (flags & EXT4_ENCRYPT_FL) 4743 if (flags & EXT4_ENCRYPT_FL)
4744 new_fl |= S_ENCRYPTED; 4744 new_fl |= S_ENCRYPTED;
4745 if (flags & EXT4_CASEFOLD_FL)
4746 new_fl |= S_CASEFOLD;
4745 inode_set_flags(inode, new_fl, 4747 inode_set_flags(inode, new_fl,
4746 S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX| 4748 S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX|
4747 S_ENCRYPTED); 4749 S_ENCRYPTED|S_CASEFOLD);
4748} 4750}
4749 4751
4750static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, 4752static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 20faa6a69238..7e85ecf0b849 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -278,6 +278,7 @@ static int ext4_ioctl_setflags(struct inode *inode,
278 struct ext4_iloc iloc; 278 struct ext4_iloc iloc;
279 unsigned int oldflags, mask, i; 279 unsigned int oldflags, mask, i;
280 unsigned int jflag; 280 unsigned int jflag;
281 struct super_block *sb = inode->i_sb;
281 282
282 /* Is it quota file? Do not allow user to mess with it */ 283 /* Is it quota file? Do not allow user to mess with it */
283 if (ext4_is_quota_file(inode)) 284 if (ext4_is_quota_file(inode))
@@ -322,6 +323,23 @@ static int ext4_ioctl_setflags(struct inode *inode,
322 goto flags_out; 323 goto flags_out;
323 } 324 }
324 325
326 if ((flags ^ oldflags) & EXT4_CASEFOLD_FL) {
327 if (!ext4_has_feature_casefold(sb)) {
328 err = -EOPNOTSUPP;
329 goto flags_out;
330 }
331
332 if (!S_ISDIR(inode->i_mode)) {
333 err = -ENOTDIR;
334 goto flags_out;
335 }
336
337 if (!ext4_empty_dir(inode)) {
338 err = -ENOTEMPTY;
339 goto flags_out;
340 }
341 }
342
325 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 343 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
326 if (IS_ERR(handle)) { 344 if (IS_ERR(handle)) {
327 err = PTR_ERR(handle); 345 err = PTR_ERR(handle);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 980166a8122a..e917830eae84 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -35,6 +35,7 @@
35#include <linux/buffer_head.h> 35#include <linux/buffer_head.h>
36#include <linux/bio.h> 36#include <linux/bio.h>
37#include <linux/iversion.h> 37#include <linux/iversion.h>
38#include <linux/unicode.h>
38#include "ext4.h" 39#include "ext4.h"
39#include "ext4_jbd2.h" 40#include "ext4_jbd2.h"
40 41
@@ -629,7 +630,7 @@ static struct stats dx_show_leaf(struct inode *dir,
629 } 630 }
630 if (!fscrypt_has_encryption_key(dir)) { 631 if (!fscrypt_has_encryption_key(dir)) {
631 /* Directory is not encrypted */ 632 /* Directory is not encrypted */
632 ext4fs_dirhash(de->name, 633 ext4fs_dirhash(dir, de->name,
633 de->name_len, &h); 634 de->name_len, &h);
634 printk("%*.s:(U)%x.%u ", len, 635 printk("%*.s:(U)%x.%u ", len,
635 name, h.hash, 636 name, h.hash,
@@ -662,8 +663,8 @@ static struct stats dx_show_leaf(struct inode *dir,
662 name = fname_crypto_str.name; 663 name = fname_crypto_str.name;
663 len = fname_crypto_str.len; 664 len = fname_crypto_str.len;
664 } 665 }
665 ext4fs_dirhash(de->name, de->name_len, 666 ext4fs_dirhash(dir, de->name,
666 &h); 667 de->name_len, &h);
667 printk("%*.s:(E)%x.%u ", len, name, 668 printk("%*.s:(E)%x.%u ", len, name,
668 h.hash, (unsigned) ((char *) de 669 h.hash, (unsigned) ((char *) de
669 - base)); 670 - base));
@@ -673,7 +674,7 @@ static struct stats dx_show_leaf(struct inode *dir,
673#else 674#else
674 int len = de->name_len; 675 int len = de->name_len;
675 char *name = de->name; 676 char *name = de->name;
676 ext4fs_dirhash(de->name, de->name_len, &h); 677 ext4fs_dirhash(dir, de->name, de->name_len, &h);
677 printk("%*.s:%x.%u ", len, name, h.hash, 678 printk("%*.s:%x.%u ", len, name, h.hash,
678 (unsigned) ((char *) de - base)); 679 (unsigned) ((char *) de - base));
679#endif 680#endif
@@ -762,7 +763,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
762 hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; 763 hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
763 hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; 764 hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
764 if (fname && fname_name(fname)) 765 if (fname && fname_name(fname))
765 ext4fs_dirhash(fname_name(fname), fname_len(fname), hinfo); 766 ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), hinfo);
766 hash = hinfo->hash; 767 hash = hinfo->hash;
767 768
768 if (root->info.unused_flags & 1) { 769 if (root->info.unused_flags & 1) {
@@ -1008,7 +1009,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
1008 /* silently ignore the rest of the block */ 1009 /* silently ignore the rest of the block */
1009 break; 1010 break;
1010 } 1011 }
1011 ext4fs_dirhash(de->name, de->name_len, hinfo); 1012 ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
1012 if ((hinfo->hash < start_hash) || 1013 if ((hinfo->hash < start_hash) ||
1013 ((hinfo->hash == start_hash) && 1014 ((hinfo->hash == start_hash) &&
1014 (hinfo->minor_hash < start_minor_hash))) 1015 (hinfo->minor_hash < start_minor_hash)))
@@ -1197,7 +1198,7 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
1197 1198
1198 while ((char *) de < base + blocksize) { 1199 while ((char *) de < base + blocksize) {
1199 if (de->name_len && de->inode) { 1200 if (de->name_len && de->inode) {
1200 ext4fs_dirhash(de->name, de->name_len, &h); 1201 ext4fs_dirhash(dir, de->name, de->name_len, &h);
1201 map_tail--; 1202 map_tail--;
1202 map_tail->hash = h.hash; 1203 map_tail->hash = h.hash;
1203 map_tail->offs = ((char *) de - base)>>2; 1204 map_tail->offs = ((char *) de - base)>>2;
@@ -1252,15 +1253,52 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
1252 dx_set_count(entries, count + 1); 1253 dx_set_count(entries, count + 1);
1253} 1254}
1254 1255
1256#ifdef CONFIG_UNICODE
1257/*
1258 * Test whether a case-insensitive directory entry matches the filename
1259 * being searched for.
1260 *
1261 * Returns: 0 if the directory entry matches, more than 0 if it
1262 * doesn't match or less than zero on error.
1263 */
1264int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
1265 const struct qstr *entry)
1266{
1267 const struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb);
1268 const struct unicode_map *um = sbi->s_encoding;
1269 int ret;
1270
1271 ret = utf8_strncasecmp(um, name, entry);
1272 if (ret < 0) {
1273 /* Handle invalid character sequence as either an error
1274 * or as an opaque byte sequence.
1275 */
1276 if (ext4_has_strict_mode(sbi))
1277 return -EINVAL;
1278
1279 if (name->len != entry->len)
1280 return 1;
1281
1282 return !!memcmp(name->name, entry->name, name->len);
1283 }
1284
1285 return ret;
1286}
1287#endif
1288
1255/* 1289/*
1256 * Test whether a directory entry matches the filename being searched for. 1290 * Test whether a directory entry matches the filename being searched for.
1257 * 1291 *
1258 * Return: %true if the directory entry matches, otherwise %false. 1292 * Return: %true if the directory entry matches, otherwise %false.
1259 */ 1293 */
1260static inline bool ext4_match(const struct ext4_filename *fname, 1294static inline bool ext4_match(const struct inode *parent,
1295 const struct ext4_filename *fname,
1261 const struct ext4_dir_entry_2 *de) 1296 const struct ext4_dir_entry_2 *de)
1262{ 1297{
1263 struct fscrypt_name f; 1298 struct fscrypt_name f;
1299#ifdef CONFIG_UNICODE
1300 const struct qstr entry = {.name = de->name, .len = de->name_len};
1301#endif
1264 1302
1265 if (!de->inode) 1303 if (!de->inode)
1266 return false; 1304 return false;
@@ -1270,6 +1308,12 @@ static inline bool ext4_match(const struct ext4_filename *fname,
1270#ifdef CONFIG_FS_ENCRYPTION 1308#ifdef CONFIG_FS_ENCRYPTION
1271 f.crypto_buf = fname->crypto_buf; 1309 f.crypto_buf = fname->crypto_buf;
1272#endif 1310#endif
1311
1312#ifdef CONFIG_UNICODE
1313 if (EXT4_SB(parent->i_sb)->s_encoding && IS_CASEFOLDED(parent))
1314 return (ext4_ci_compare(parent, fname->usr_fname, &entry) == 0);
1315#endif
1316
1273 return fscrypt_match_name(&f, de->name, de->name_len); 1317 return fscrypt_match_name(&f, de->name, de->name_len);
1274} 1318}
1275 1319
@@ -1290,7 +1334,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
1290 /* this code is executed quadratically often */ 1334 /* this code is executed quadratically often */
1291 /* do minimal checking `by hand' */ 1335 /* do minimal checking `by hand' */
1292 if ((char *) de + de->name_len <= dlimit && 1336 if ((char *) de + de->name_len <= dlimit &&
1293 ext4_match(fname, de)) { 1337 ext4_match(dir, fname, de)) {
1294 /* found a match - just to be sure, do 1338 /* found a match - just to be sure, do
1295 * a full check */ 1339 * a full check */
1296 if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, 1340 if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
@@ -1588,6 +1632,17 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
1588 return ERR_PTR(-EPERM); 1632 return ERR_PTR(-EPERM);
1589 } 1633 }
1590 } 1634 }
1635
1636#ifdef CONFIG_UNICODE
1637 if (!inode && IS_CASEFOLDED(dir)) {
1638 /* Eventually we want to call d_add_ci(dentry, NULL)
1639 * for negative dentries in the encoding case as
1640 * well. For now, prevent the negative dentry
1641 * from being cached.
1642 */
1643 return NULL;
1644 }
1645#endif
1591 return d_splice_alias(inode, dentry); 1646 return d_splice_alias(inode, dentry);
1592} 1647}
1593 1648
@@ -1798,7 +1853,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
1798 if (ext4_check_dir_entry(dir, NULL, de, bh, 1853 if (ext4_check_dir_entry(dir, NULL, de, bh,
1799 buf, buf_size, offset)) 1854 buf, buf_size, offset))
1800 return -EFSCORRUPTED; 1855 return -EFSCORRUPTED;
1801 if (ext4_match(fname, de)) 1856 if (ext4_match(dir, fname, de))
1802 return -EEXIST; 1857 return -EEXIST;
1803 nlen = EXT4_DIR_REC_LEN(de->name_len); 1858 nlen = EXT4_DIR_REC_LEN(de->name_len);
1804 rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); 1859 rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
@@ -1983,7 +2038,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
1983 if (fname->hinfo.hash_version <= DX_HASH_TEA) 2038 if (fname->hinfo.hash_version <= DX_HASH_TEA)
1984 fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; 2039 fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
1985 fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; 2040 fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
1986 ext4fs_dirhash(fname_name(fname), fname_len(fname), &fname->hinfo); 2041 ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), &fname->hinfo);
1987 2042
1988 memset(frames, 0, sizeof(frames)); 2043 memset(frames, 0, sizeof(frames));
1989 frame = frames; 2044 frame = frames;
@@ -2036,6 +2091,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
2036 struct ext4_dir_entry_2 *de; 2091 struct ext4_dir_entry_2 *de;
2037 struct ext4_dir_entry_tail *t; 2092 struct ext4_dir_entry_tail *t;
2038 struct super_block *sb; 2093 struct super_block *sb;
2094 struct ext4_sb_info *sbi;
2039 struct ext4_filename fname; 2095 struct ext4_filename fname;
2040 int retval; 2096 int retval;
2041 int dx_fallback=0; 2097 int dx_fallback=0;
@@ -2047,10 +2103,17 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
2047 csum_size = sizeof(struct ext4_dir_entry_tail); 2103 csum_size = sizeof(struct ext4_dir_entry_tail);
2048 2104
2049 sb = dir->i_sb; 2105 sb = dir->i_sb;
2106 sbi = EXT4_SB(sb);
2050 blocksize = sb->s_blocksize; 2107 blocksize = sb->s_blocksize;
2051 if (!dentry->d_name.len) 2108 if (!dentry->d_name.len)
2052 return -EINVAL; 2109 return -EINVAL;
2053 2110
2111#ifdef CONFIG_UNICODE
2112 if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
2113 utf8_validate(sbi->s_encoding, &dentry->d_name))
2114 return -EINVAL;
2115#endif
2116
2054 retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname); 2117 retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
2055 if (retval) 2118 if (retval)
2056 return retval; 2119 return retval;
@@ -2975,6 +3038,17 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
2975 ext4_update_dx_flag(dir); 3038 ext4_update_dx_flag(dir);
2976 ext4_mark_inode_dirty(handle, dir); 3039 ext4_mark_inode_dirty(handle, dir);
2977 3040
3041#ifdef CONFIG_UNICODE
3042 /* VFS negative dentries are incompatible with Encoding and
3043 * Case-insensitiveness. Eventually we'll want avoid
3044 * invalidating the dentries here, alongside with returning the
3045 * negative dentries at ext4_lookup(), when it is better
3046 * supported by the VFS for the CI case.
3047 */
3048 if (IS_CASEFOLDED(dir))
3049 d_invalidate(dentry);
3050#endif
3051
2978end_rmdir: 3052end_rmdir:
2979 brelse(bh); 3053 brelse(bh);
2980 if (handle) 3054 if (handle)
@@ -3044,6 +3118,17 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
3044 inode->i_ctime = current_time(inode); 3118 inode->i_ctime = current_time(inode);
3045 ext4_mark_inode_dirty(handle, inode); 3119 ext4_mark_inode_dirty(handle, inode);
3046 3120
3121#ifdef CONFIG_UNICODE
3122 /* VFS negative dentries are incompatible with Encoding and
3123 * Case-insensitiveness. Eventually we'll want avoid
3124 * invalidating the dentries here, alongside with returning the
3125 * negative dentries at ext4_lookup(), when it is better
3126 * supported by the VFS for the CI case.
3127 */
3128 if (IS_CASEFOLDED(dir))
3129 d_invalidate(dentry);
3130#endif
3131
3047end_unlink: 3132end_unlink:
3048 brelse(bh); 3133 brelse(bh);
3049 if (handle) 3134 if (handle)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c1b02c3a5a68..aeb6d22ea0ad 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4484,6 +4484,12 @@ no_journal:
4484 iput(root); 4484 iput(root);
4485 goto failed_mount4; 4485 goto failed_mount4;
4486 } 4486 }
4487
4488#ifdef CONFIG_UNICODE
4489 if (sbi->s_encoding)
4490 sb->s_d_op = &ext4_dentry_ops;
4491#endif
4492
4487 sb->s_root = d_make_root(root); 4493 sb->s_root = d_make_root(root);
4488 if (!sb->s_root) { 4494 if (!sb->s_root) {
4489 ext4_msg(sb, KERN_ERR, "get root dentry failed"); 4495 ext4_msg(sb, KERN_ERR, "get root dentry failed");
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8b42df09b04c..6261090e605b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1953,6 +1953,7 @@ struct super_operations {
1953#define S_DAX 0 /* Make all the DAX code disappear */ 1953#define S_DAX 0 /* Make all the DAX code disappear */
1954#endif 1954#endif
1955#define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */ 1955#define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */
1956#define S_CASEFOLD 32768 /* Casefolded file */
1956 1957
1957/* 1958/*
1958 * Note that nosuid etc flags are inode-specific: setting some file-system 1959 * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -1993,6 +1994,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags
1993#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC) 1994#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
1994#define IS_DAX(inode) ((inode)->i_flags & S_DAX) 1995#define IS_DAX(inode) ((inode)->i_flags & S_DAX)
1995#define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED) 1996#define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED)
1997#define IS_CASEFOLDED(inode) ((inode)->i_flags & S_CASEFOLD)
1996 1998
1997#define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \ 1999#define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \
1998 (inode)->i_rdev == WHITEOUT_DEV) 2000 (inode)->i_rdev == WHITEOUT_DEV)