Merge tag 'f2fs-for-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeu...
[linux-2.6-microblaze.git] / fs / f2fs / dir.c
index 53fbc4d..4b9ef8b 100644 (file)
@@ -75,21 +75,22 @@ int f2fs_init_casefolded_name(const struct inode *dir,
                              struct f2fs_filename *fname)
 {
 #ifdef CONFIG_UNICODE
-       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
 
        if (IS_CASEFOLDED(dir)) {
                fname->cf_name.name = f2fs_kmalloc(sbi, F2FS_NAME_LEN,
                                                   GFP_NOFS);
                if (!fname->cf_name.name)
                        return -ENOMEM;
-               fname->cf_name.len = utf8_casefold(sbi->s_encoding,
+               fname->cf_name.len = utf8_casefold(sb->s_encoding,
                                                   fname->usr_fname,
                                                   fname->cf_name.name,
                                                   F2FS_NAME_LEN);
                if ((int)fname->cf_name.len <= 0) {
                        kfree(fname->cf_name.name);
                        fname->cf_name.name = NULL;
-                       if (f2fs_has_strict_mode(sbi))
+                       if (sb_has_strict_encoding(sb))
                                return -EINVAL;
                        /* fall back to treating name as opaque byte sequence */
                }
@@ -190,21 +191,15 @@ static unsigned long dir_block_index(unsigned int level,
 static struct f2fs_dir_entry *find_in_block(struct inode *dir,
                                struct page *dentry_page,
                                const struct f2fs_filename *fname,
-                               int *max_slots,
-                               struct page **res_page)
+                               int *max_slots)
 {
        struct f2fs_dentry_block *dentry_blk;
-       struct f2fs_dir_entry *de;
        struct f2fs_dentry_ptr d;
 
        dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);
 
        make_dentry_ptr_block(dir, &d, dentry_blk);
-       de = f2fs_find_target_dentry(&d, fname, max_slots);
-       if (de)
-               *res_page = dentry_page;
-
-       return de;
+       return f2fs_find_target_dentry(&d, fname, max_slots);
 }
 
 #ifdef CONFIG_UNICODE
@@ -215,8 +210,8 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
 static bool f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,
                               const u8 *de_name, u32 de_name_len)
 {
-       const struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
-       const struct unicode_map *um = sbi->s_encoding;
+       const struct super_block *sb = dir->i_sb;
+       const struct unicode_map *um = sb->s_encoding;
        struct qstr entry = QSTR_INIT(de_name, de_name_len);
        int res;
 
@@ -226,7 +221,7 @@ static bool f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,
                 * In strict mode, ignore invalid names.  In non-strict mode,
                 * fall back to treating them as opaque byte sequences.
                 */
-               if (f2fs_has_strict_mode(sbi) || name->len != entry.len)
+               if (sb_has_strict_encoding(sb) || name->len != entry.len)
                        return false;
                return !memcmp(name->name, entry.name, name->len);
        }
@@ -330,10 +325,11 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
                        }
                }
 
-               de = find_in_block(dir, dentry_page, fname, &max_slots,
-                                  res_page);
-               if (de)
+               de = find_in_block(dir, dentry_page, fname, &max_slots);
+               if (de) {
+                       *res_page = dentry_page;
                        break;
+               }
 
                if (max_slots >= s)
                        room = true;
@@ -357,16 +353,15 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
        unsigned int max_depth;
        unsigned int level;
 
+       *res_page = NULL;
+
        if (f2fs_has_inline_dentry(dir)) {
-               *res_page = NULL;
                de = f2fs_find_in_inline_dir(dir, fname, res_page);
                goto out;
        }
 
-       if (npages == 0) {
-               *res_page = NULL;
+       if (npages == 0)
                goto out;
-       }
 
        max_depth = F2FS_I(dir)->i_current_depth;
        if (unlikely(max_depth > MAX_DIR_HASH_DEPTH)) {
@@ -377,7 +372,6 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
        }
 
        for (level = 0; level < max_depth; level++) {
-               *res_page = NULL;
                de = find_in_level(dir, level, fname, res_page);
                if (de || IS_ERR(*res_page))
                        break;
@@ -1107,75 +1101,8 @@ const struct file_operations f2fs_dir_operations = {
 };
 
 #ifdef CONFIG_UNICODE
-static int f2fs_d_compare(const struct dentry *dentry, unsigned int len,
-                         const char *str, const struct qstr *name)
-{
-       const struct dentry *parent = READ_ONCE(dentry->d_parent);
-       const struct inode *dir = READ_ONCE(parent->d_inode);
-       const struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-       struct qstr entry = QSTR_INIT(str, len);
-       char strbuf[DNAME_INLINE_LEN];
-       int res;
-
-       if (!dir || !IS_CASEFOLDED(dir))
-               goto fallback;
-
-       /*
-        * If the dentry name is stored in-line, then it may be concurrently
-        * modified by a rename.  If this happens, the VFS will eventually retry
-        * the lookup, so it doesn't matter what ->d_compare() returns.
-        * However, it's unsafe to call utf8_strncasecmp() with an unstable
-        * string.  Therefore, we have to copy the name into a temporary buffer.
-        */
-       if (len <= DNAME_INLINE_LEN - 1) {
-               memcpy(strbuf, str, len);
-               strbuf[len] = 0;
-               entry.name = strbuf;
-               /* prevent compiler from optimizing out the temporary buffer */
-               barrier();
-       }
-
-       res = utf8_strncasecmp(sbi->s_encoding, name, &entry);
-       if (res >= 0)
-               return res;
-
-       if (f2fs_has_strict_mode(sbi))
-               return -EINVAL;
-fallback:
-       if (len != name->len)
-               return 1;
-       return !!memcmp(str, name->name, len);
-}
-
-static int f2fs_d_hash(const struct dentry *dentry, struct qstr *str)
-{
-       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-       const struct unicode_map *um = sbi->s_encoding;
-       const struct inode *inode = READ_ONCE(dentry->d_inode);
-       unsigned char *norm;
-       int len, ret = 0;
-
-       if (!inode || !IS_CASEFOLDED(inode))
-               return 0;
-
-       norm = f2fs_kmalloc(sbi, PATH_MAX, GFP_ATOMIC);
-       if (!norm)
-               return -ENOMEM;
-
-       len = utf8_casefold(um, str, norm, PATH_MAX);
-       if (len < 0) {
-               if (f2fs_has_strict_mode(sbi))
-                       ret = -EINVAL;
-               goto out;
-       }
-       str->hash = full_name_hash(dentry, norm, len);
-out:
-       kvfree(norm);
-       return ret;
-}
-
 const struct dentry_operations f2fs_dentry_ops = {
-       .d_hash = f2fs_d_hash,
-       .d_compare = f2fs_d_compare,
+       .d_hash = generic_ci_d_hash,
+       .d_compare = generic_ci_d_compare,
 };
 #endif