1 ext4: Support case-insensitive file name lookups
3 From: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
5 This patch implements the actual support for case-insensitive file name
6 lookups in ext4, based on the feature bit and the encoding stored in the
9 A filesystem that has the fname_encoding feature set is able to
10 configure directories with the +F (EXT4_CASEFOLD_FL) attribute, enabling
11 lookups to succeed in that directory in a case-insensitive fashion, i.e:
12 match a directory entry even if the name used by userspace is not a byte
13 per byte match with the disk name, but is an equivalent case-insensitive
14 version of the Unicode string. This operation is called a
15 case-insensitive file name lookup.
17 The feature is configured as an inode attribute applied to directories
18 and inherited by its children. This attribute can only be enabled on
19 empty directories for filesystems that support the encoding feature,
20 thus preventing collision of file names that only differ by case.
24 For a +F directory, Ext4 only stores the first equivalent name dentry
25 used in the dcache. This is done to prevent unintentional duplication of
26 dentries in the dcache, while also allowing the VFS code to quickly find
27 the right entry in the cache despite which equivalent string was used in
28 a previous lookup, without having to resort to ->lookup().
30 d_hash() of casefolded directories is implemented as the hash of the
31 casefolded string, such that we always have a well-known bucket for all
32 the equivalencies of the same string. d_compare() uses the
33 utf8_strncasecmp() infrastructure, which handles the comparison of
34 equivalent, same case, names as well.
36 For now, negative lookups are not inserted in the dcache, since they
37 would need to be invalidated anyway, because we can't trust missing file
38 dentries. This is bad for performance but requires some leveraging of
39 the vfs layer to fix. We can live without that for now, and so does
44 Despite using a specific version of the name as the internal
45 representation within the dcache, the name stored and fetched from the
46 disk is a byte-per-byte match with what the user requested, making this
47 implementation 'name-preserving'. i.e. no actual information is lost
48 when writing to storage.
50 DX is supported by modifying the hashes used in +F directories to make
51 them case/encoding-aware. The new disk hashes are calculated as the
52 hash of the full casefolded string, instead of the string directly.
53 This allows us to efficiently search for file names in the htree without
54 requiring the user to provide an exact name.
56 * Dealing with invalid sequences:
58 By default, when a invalid UTF-8 sequence is identified, ext4 will treat
59 it as an opaque byte sequence, ignoring the encoding and reverting to
60 the old behavior for that unique file. This means that case-insensitive
61 file name lookup will not work only for that file. An optional bit can
62 be set in the superblock telling the filesystem code and userspace tools
63 to enforce the encoding. When that optional bit is set, any attempt to
64 create a file name using an invalid UTF-8 sequence will fail and return
65 an error to userspace.
67 * Normalization algorithm:
69 The UTF-8 algorithms used to compare strings in ext4 is implemented
70 lives in fs/unicode, and is based on a previous version developed by
71 SGI. It implements the Canonical decomposition (NFD) algorithm
72 described by the Unicode specification 12.1, or higher, combined with
73 the elimination of ignorable code points (NFDi) and full
74 case-folding (CF) as documented in fs/unicode/utf8_norm.c.
76 NFD seems to be the best normalization method for EXT4 because:
78 - It has a lower cost than NFC/NFKC (which requires
79 decomposing to NFD as an intermediary step)
80 - It doesn't eliminate important semantic meaning like
81 compatibility decompositions.
85 - This implementation is not completely linguistic accurate, because
86 different languages have conflicting rules, which would require the
87 specialization of the filesystem to a given locale, which brings all
88 sorts of problems for removable media and for users who use more than
91 Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
92 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
94 fs/ext4/dir.c | 48 +++++++++++++++++++++++++++++++++++
95 fs/ext4/ext4.h | 21 ++++++++++-----
96 fs/ext4/hash.c | 34 ++++++++++++++++++++++++-
97 fs/ext4/ialloc.c | 2 +-
98 fs/ext4/inline.c | 2 +-
99 fs/ext4/inode.c | 4 ++-
100 fs/ext4/ioctl.c | 18 +++++++++++++
101 fs/ext4/namei.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
102 fs/ext4/super.c | 6 +++++
103 include/linux/fs.h | 2 ++
104 10 files changed, 223 insertions(+), 21 deletions(-)
106 diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
107 index 0ccd51f72048..884a6e776809 100644
111 #include <linux/buffer_head.h>
112 #include <linux/slab.h>
113 #include <linux/iversion.h>
114 +#include <linux/unicode.h>
118 @@ -660,3 +661,50 @@ const struct file_operations ext4_dir_operations = {
119 .open = ext4_dir_open,
120 .release = ext4_release_dir,
123 +#ifdef CONFIG_UNICODE
124 +static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
125 + const char *str, const struct qstr *name)
127 + struct qstr qstr = {.name = str, .len = len };
129 + if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
130 + if (len != name->len)
132 + return !memcmp(str, name, len);
135 + return ext4_ci_compare(dentry->d_parent->d_inode, name, &qstr);
138 +static int ext4_d_hash(const struct dentry *dentry, struct qstr *str)
140 + const struct ext4_sb_info *sbi = EXT4_SB(dentry->d_sb);
141 + const struct unicode_map *um = sbi->s_encoding;
142 + unsigned char *norm;
145 + if (!IS_CASEFOLDED(dentry->d_inode))
148 + norm = kmalloc(PATH_MAX, GFP_ATOMIC);
152 + len = utf8_casefold(um, str, norm, PATH_MAX);
154 + if (ext4_has_strict_mode(sbi))
158 + str->hash = full_name_hash(dentry, norm, len);
164 +const struct dentry_operations ext4_dentry_ops = {
165 + .d_hash = ext4_d_hash,
166 + .d_compare = ext4_d_compare,
169 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
170 index 2219b4f4a593..dc0d4b4a0119 100644
173 @@ -399,10 +399,11 @@ struct flex_groups {
174 #define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */
175 #define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */
176 #define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
177 +#define EXT4_CASEFOLD_FL 0x40000000 /* Casefolded file */
178 #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
180 -#define EXT4_FL_USER_VISIBLE 0x304BDFFF /* User visible flags */
181 -#define EXT4_FL_USER_MODIFIABLE 0x204BC0FF /* User modifiable flags */
182 +#define EXT4_FL_USER_VISIBLE 0x704BDFFF /* User visible flags */
183 +#define EXT4_FL_USER_MODIFIABLE 0x604BC0FF /* User modifiable flags */
185 /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
186 #define EXT4_FL_XFLAG_VISIBLE (EXT4_SYNC_FL | \
187 @@ -417,10 +418,10 @@ struct flex_groups {
188 EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
189 EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
190 EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\
191 - EXT4_PROJINHERIT_FL)
192 + EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL)
194 /* Flags that are appropriate for regular files (all but dir-specific ones). */
195 -#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL))
196 +#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL | EXT4_CASEFOLD_FL))
198 /* Flags that are appropriate for non-directories/regular files. */
199 #define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL)
200 @@ -2393,8 +2394,8 @@ extern int ext4_check_all_de(struct inode *dir, struct buffer_head *bh,
201 extern int ext4_sync_file(struct file *, loff_t, loff_t, int);
204 -extern int ext4fs_dirhash(const char *name, int len, struct
205 - dx_hash_info *hinfo);
206 +extern int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
207 + struct dx_hash_info *hinfo);
210 extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t,
211 @@ -2990,6 +2991,10 @@ static inline void ext4_unlock_group(struct super_block *sb,
213 extern const struct file_operations ext4_dir_operations;
215 +#ifdef CONFIG_UNICODE
216 +extern const struct dentry_operations ext4_dentry_ops;
220 extern const struct inode_operations ext4_file_inode_operations;
221 extern const struct file_operations ext4_file_operations;
222 @@ -3082,6 +3087,10 @@ extern void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
223 extern int ext4_handle_dirty_dirent_node(handle_t *handle,
225 struct buffer_head *bh);
226 +extern int ext4_ci_compare(const struct inode *parent,
227 + const struct qstr *name,
228 + const struct qstr *entry);
231 static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
232 [S_IFREG >> S_SHIFT] = EXT4_FT_REG_FILE,
233 diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
234 index 46b24da33a28..d358bfcb6b3f 100644
240 #include <linux/fs.h>
241 +#include <linux/unicode.h>
242 #include <linux/compiler.h>
243 #include <linux/bitops.h>
245 @@ -196,7 +197,8 @@ static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)
246 * represented, and whether or not the returned hash is 32 bits or 64
247 * bits. 32 bit hashes will return 0 for the minor hash.
249 -int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
250 +static int __ext4fs_dirhash(const char *name, int len,
251 + struct dx_hash_info *hinfo)
254 __u32 minor_hash = 0;
255 @@ -268,3 +270,33 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
256 hinfo->minor_hash = minor_hash;
260 +int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
261 + struct dx_hash_info *hinfo)
263 +#ifdef CONFIG_UNICODE
264 + const struct unicode_map *um = EXT4_SB(dir->i_sb)->s_encoding;
266 + unsigned char *buff;
267 + struct qstr qstr = {.name = name, .len = len };
269 + if (len && IS_CASEFOLDED(dir)) {
270 + buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
274 + dlen = utf8_casefold(um, &qstr, buff, PATH_MAX);
280 + r = __ext4fs_dirhash(buff, dlen, hinfo);
287 + return __ext4fs_dirhash(name, len, hinfo);
289 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
290 index f3e17a8c84b4..764ff4c56233 100644
291 --- a/fs/ext4/ialloc.c
292 +++ b/fs/ext4/ialloc.c
293 @@ -455,7 +455,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
295 hinfo.hash_version = DX_HASH_HALF_MD4;
296 hinfo.seed = sbi->s_hash_seed;
297 - ext4fs_dirhash(qstr->name, qstr->len, &hinfo);
298 + ext4fs_dirhash(parent, qstr->name, qstr->len, &hinfo);
302 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
303 index 56f6e1782d5f..f73bc3925282 100644
304 --- a/fs/ext4/inline.c
305 +++ b/fs/ext4/inline.c
306 @@ -1407,7 +1407,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
310 - ext4fs_dirhash(de->name, de->name_len, hinfo);
311 + ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
312 if ((hinfo->hash < start_hash) ||
313 ((hinfo->hash == start_hash) &&
314 (hinfo->minor_hash < start_minor_hash)))
315 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
316 index 609c8366d029..82298c63ea6d 100644
317 --- a/fs/ext4/inode.c
318 +++ b/fs/ext4/inode.c
319 @@ -4742,9 +4742,11 @@ void ext4_set_inode_flags(struct inode *inode)
321 if (flags & EXT4_ENCRYPT_FL)
322 new_fl |= S_ENCRYPTED;
323 + if (flags & EXT4_CASEFOLD_FL)
324 + new_fl |= S_CASEFOLD;
325 inode_set_flags(inode, new_fl,
326 S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX|
328 + S_ENCRYPTED|S_CASEFOLD);
331 static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
332 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
333 index 20faa6a69238..e14e6c5ede9d 100644
334 --- a/fs/ext4/ioctl.c
335 +++ b/fs/ext4/ioctl.c
336 @@ -278,6 +278,7 @@ static int ext4_ioctl_setflags(struct inode *inode,
337 struct ext4_iloc iloc;
338 unsigned int oldflags, mask, i;
340 + struct super_block *sb = inode->i_sb;
342 /* Is it quota file? Do not allow user to mess with it */
343 if (ext4_is_quota_file(inode))
344 @@ -322,6 +323,23 @@ static int ext4_ioctl_setflags(struct inode *inode,
348 + if ((flags ^ oldflags) & EXT4_CASEFOLD_FL) {
349 + if (!ext4_has_feature_fname_encoding(sb)) {
354 + if (!S_ISDIR(inode->i_mode)) {
359 + if (!ext4_empty_dir(inode)) {
365 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
366 if (IS_ERR(handle)) {
367 err = PTR_ERR(handle);
368 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
369 index 980166a8122a..e917830eae84 100644
370 --- a/fs/ext4/namei.c
371 +++ b/fs/ext4/namei.c
373 #include <linux/buffer_head.h>
374 #include <linux/bio.h>
375 #include <linux/iversion.h>
376 +#include <linux/unicode.h>
378 #include "ext4_jbd2.h"
380 @@ -629,7 +630,7 @@ static struct stats dx_show_leaf(struct inode *dir,
382 if (!fscrypt_has_encryption_key(dir)) {
383 /* Directory is not encrypted */
384 - ext4fs_dirhash(de->name,
385 + ext4fs_dirhash(dir, de->name,
387 printk("%*.s:(U)%x.%u ", len,
389 @@ -662,8 +663,8 @@ static struct stats dx_show_leaf(struct inode *dir,
390 name = fname_crypto_str.name;
391 len = fname_crypto_str.len;
393 - ext4fs_dirhash(de->name, de->name_len,
395 + ext4fs_dirhash(dir, de->name,
397 printk("%*.s:(E)%x.%u ", len, name,
398 h.hash, (unsigned) ((char *) de
400 @@ -673,7 +674,7 @@ static struct stats dx_show_leaf(struct inode *dir,
402 int len = de->name_len;
403 char *name = de->name;
404 - ext4fs_dirhash(de->name, de->name_len, &h);
405 + ext4fs_dirhash(dir, de->name, de->name_len, &h);
406 printk("%*.s:%x.%u ", len, name, h.hash,
407 (unsigned) ((char *) de - base));
409 @@ -762,7 +763,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
410 hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
411 hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
412 if (fname && fname_name(fname))
413 - ext4fs_dirhash(fname_name(fname), fname_len(fname), hinfo);
414 + ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), hinfo);
417 if (root->info.unused_flags & 1) {
418 @@ -1008,7 +1009,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
419 /* silently ignore the rest of the block */
422 - ext4fs_dirhash(de->name, de->name_len, hinfo);
423 + ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
424 if ((hinfo->hash < start_hash) ||
425 ((hinfo->hash == start_hash) &&
426 (hinfo->minor_hash < start_minor_hash)))
427 @@ -1197,7 +1198,7 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
429 while ((char *) de < base + blocksize) {
430 if (de->name_len && de->inode) {
431 - ext4fs_dirhash(de->name, de->name_len, &h);
432 + ext4fs_dirhash(dir, de->name, de->name_len, &h);
434 map_tail->hash = h.hash;
435 map_tail->offs = ((char *) de - base)>>2;
436 @@ -1252,15 +1253,52 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
437 dx_set_count(entries, count + 1);
440 +#ifdef CONFIG_UNICODE
442 + * Test whether a case-insensitive directory entry matches the filename
443 + * being searched for.
445 + * Returns: 0 if the directory entry matches, more than 0 if it
446 + * doesn't match or less than zero on error.
448 +int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
449 + const struct qstr *entry)
451 + const struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb);
452 + const struct unicode_map *um = sbi->s_encoding;
455 + ret = utf8_strncasecmp(um, name, entry);
457 + /* Handle invalid character sequence as either an error
458 + * or as an opaque byte sequence.
460 + if (ext4_has_strict_mode(sbi))
463 + if (name->len != entry->len)
466 + return !!memcmp(name->name, entry->name, name->len);
474 * Test whether a directory entry matches the filename being searched for.
476 * Return: %true if the directory entry matches, otherwise %false.
478 -static inline bool ext4_match(const struct ext4_filename *fname,
479 +static inline bool ext4_match(const struct inode *parent,
480 + const struct ext4_filename *fname,
481 const struct ext4_dir_entry_2 *de)
483 struct fscrypt_name f;
484 +#ifdef CONFIG_UNICODE
485 + const struct qstr entry = {.name = de->name, .len = de->name_len};
490 @@ -1270,6 +1308,12 @@ static inline bool ext4_match(const struct ext4_filename *fname,
491 #ifdef CONFIG_FS_ENCRYPTION
492 f.crypto_buf = fname->crypto_buf;
495 +#ifdef CONFIG_UNICODE
496 + if (EXT4_SB(parent->i_sb)->s_encoding && IS_CASEFOLDED(parent))
497 + return (ext4_ci_compare(parent, fname->usr_fname, &entry) == 0);
500 return fscrypt_match_name(&f, de->name, de->name_len);
503 @@ -1290,7 +1334,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
504 /* this code is executed quadratically often */
505 /* do minimal checking `by hand' */
506 if ((char *) de + de->name_len <= dlimit &&
507 - ext4_match(fname, de)) {
508 + ext4_match(dir, fname, de)) {
509 /* found a match - just to be sure, do
511 if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
512 @@ -1588,6 +1632,17 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
513 return ERR_PTR(-EPERM);
517 +#ifdef CONFIG_UNICODE
518 + if (!inode && IS_CASEFOLDED(dir)) {
519 + /* Eventually we want to call d_add_ci(dentry, NULL)
520 + * for negative dentries in the encoding case as
521 + * well. For now, prevent the negative dentry
522 + * from being cached.
527 return d_splice_alias(inode, dentry);
530 @@ -1798,7 +1853,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
531 if (ext4_check_dir_entry(dir, NULL, de, bh,
532 buf, buf_size, offset))
533 return -EFSCORRUPTED;
534 - if (ext4_match(fname, de))
535 + if (ext4_match(dir, fname, de))
537 nlen = EXT4_DIR_REC_LEN(de->name_len);
538 rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
539 @@ -1983,7 +2038,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
540 if (fname->hinfo.hash_version <= DX_HASH_TEA)
541 fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
542 fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
543 - ext4fs_dirhash(fname_name(fname), fname_len(fname), &fname->hinfo);
544 + ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), &fname->hinfo);
546 memset(frames, 0, sizeof(frames));
548 @@ -2036,6 +2091,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
549 struct ext4_dir_entry_2 *de;
550 struct ext4_dir_entry_tail *t;
551 struct super_block *sb;
552 + struct ext4_sb_info *sbi;
553 struct ext4_filename fname;
556 @@ -2047,10 +2103,17 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
557 csum_size = sizeof(struct ext4_dir_entry_tail);
561 blocksize = sb->s_blocksize;
562 if (!dentry->d_name.len)
565 +#ifdef CONFIG_UNICODE
566 + if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
567 + utf8_validate(sbi->s_encoding, &dentry->d_name))
571 retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
574 @@ -2975,6 +3038,17 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
575 ext4_update_dx_flag(dir);
576 ext4_mark_inode_dirty(handle, dir);
578 +#ifdef CONFIG_UNICODE
579 + /* VFS negative dentries are incompatible with Encoding and
580 + * Case-insensitiveness. Eventually we'll want avoid
581 + * invalidating the dentries here, alongside with returning the
582 + * negative dentries at ext4_lookup(), when it is better
583 + * supported by the VFS for the CI case.
585 + if (IS_CASEFOLDED(dir))
586 + d_invalidate(dentry);
592 @@ -3044,6 +3118,17 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
593 inode->i_ctime = current_time(inode);
594 ext4_mark_inode_dirty(handle, inode);
596 +#ifdef CONFIG_UNICODE
597 + /* VFS negative dentries are incompatible with Encoding and
598 + * Case-insensitiveness. Eventually we'll want avoid
599 + * invalidating the dentries here, alongside with returning the
600 + * negative dentries at ext4_lookup(), when it is better
601 + * supported by the VFS for the CI case.
603 + if (IS_CASEFOLDED(dir))
604 + d_invalidate(dentry);
610 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
611 index 934814d0a041..c17d300a9f16 100644
612 --- a/fs/ext4/super.c
613 +++ b/fs/ext4/super.c
614 @@ -4484,6 +4484,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
619 +#ifdef CONFIG_UNICODE
620 + if (sbi->s_encoding)
621 + sb->s_d_op = &ext4_dentry_ops;
624 sb->s_root = d_make_root(root);
626 ext4_msg(sb, KERN_ERR, "get root dentry failed");
627 diff --git a/include/linux/fs.h b/include/linux/fs.h
628 index 8b42df09b04c..6261090e605b 100644
629 --- a/include/linux/fs.h
630 +++ b/include/linux/fs.h
631 @@ -1953,6 +1953,7 @@ struct super_operations {
632 #define S_DAX 0 /* Make all the DAX code disappear */
634 #define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */
635 +#define S_CASEFOLD 32768 /* Casefolded file */
638 * Note that nosuid etc flags are inode-specific: setting some file-system
639 @@ -1993,6 +1994,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags
640 #define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
641 #define IS_DAX(inode) ((inode)->i_flags & S_DAX)
642 #define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED)
643 +#define IS_CASEFOLDED(inode) ((inode)->i_flags & S_CASEFOLD)
645 #define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \
646 (inode)->i_rdev == WHITEOUT_DEV)