Merge tag 'f2fs-for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[sfrench/cifs-2.6.git] / fs / f2fs / namei.c
index c227113b0f2621d77fa26432807e6e47d94fd263..6032589099ce40ce2a59772cfb4bfdb0932f1116 100644 (file)
 #include "acl.h"
 #include <trace/events/f2fs.h>
 
-static struct inode *f2fs_new_inode(struct user_namespace *mnt_userns,
-                                               struct inode *dir, umode_t mode)
-{
-       struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
-       nid_t ino;
-       struct inode *inode;
-       bool nid_free = false;
-       bool encrypt = false;
-       int xattr_size = 0;
-       int err;
-
-       inode = new_inode(dir->i_sb);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
-
-       if (!f2fs_alloc_nid(sbi, &ino)) {
-               err = -ENOSPC;
-               goto fail;
-       }
-
-       nid_free = true;
-
-       inode_init_owner(mnt_userns, inode, dir, mode);
-
-       inode->i_ino = ino;
-       inode->i_blocks = 0;
-       inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
-       F2FS_I(inode)->i_crtime = inode->i_mtime;
-       inode->i_generation = get_random_u32();
-
-       if (S_ISDIR(inode->i_mode))
-               F2FS_I(inode)->i_current_depth = 1;
-
-       err = insert_inode_locked(inode);
-       if (err) {
-               err = -EINVAL;
-               goto fail;
-       }
-
-       if (f2fs_sb_has_project_quota(sbi) &&
-               (F2FS_I(dir)->i_flags & F2FS_PROJINHERIT_FL))
-               F2FS_I(inode)->i_projid = F2FS_I(dir)->i_projid;
-       else
-               F2FS_I(inode)->i_projid = make_kprojid(mnt_userns,
-                                                       F2FS_DEF_PROJID);
-
-       err = fscrypt_prepare_new_inode(dir, inode, &encrypt);
-       if (err)
-               goto fail_drop;
-
-       err = f2fs_dquot_initialize(inode);
-       if (err)
-               goto fail_drop;
-
-       set_inode_flag(inode, FI_NEW_INODE);
-
-       if (encrypt)
-               f2fs_set_encrypted_inode(inode);
-
-       if (f2fs_sb_has_extra_attr(sbi)) {
-               set_inode_flag(inode, FI_EXTRA_ATTR);
-               F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;
-       }
-
-       if (test_opt(sbi, INLINE_XATTR))
-               set_inode_flag(inode, FI_INLINE_XATTR);
-
-       if (f2fs_may_inline_dentry(inode))
-               set_inode_flag(inode, FI_INLINE_DENTRY);
-
-       if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
-               f2fs_bug_on(sbi, !f2fs_has_extra_attr(inode));
-               if (f2fs_has_inline_xattr(inode))
-                       xattr_size = F2FS_OPTION(sbi).inline_xattr_size;
-               /* Otherwise, will be 0 */
-       } else if (f2fs_has_inline_xattr(inode) ||
-                               f2fs_has_inline_dentry(inode)) {
-               xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
-       }
-       F2FS_I(inode)->i_inline_xattr_size = xattr_size;
-
-       f2fs_init_extent_tree(inode, NULL);
-
-       F2FS_I(inode)->i_flags =
-               f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED);
-
-       if (S_ISDIR(inode->i_mode))
-               F2FS_I(inode)->i_flags |= F2FS_INDEX_FL;
-
-       if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL)
-               set_inode_flag(inode, FI_PROJ_INHERIT);
-
-       if (f2fs_sb_has_compression(sbi)) {
-               /* Inherit the compression flag in directory */
-               if ((F2FS_I(dir)->i_flags & F2FS_COMPR_FL) &&
-                                       f2fs_may_compress(inode))
-                       set_compress_context(inode);
-       }
-
-       /* Should enable inline_data after compression set */
-       if (test_opt(sbi, INLINE_DATA) && f2fs_may_inline_data(inode))
-               set_inode_flag(inode, FI_INLINE_DATA);
-
-       stat_inc_inline_xattr(inode);
-       stat_inc_inline_inode(inode);
-       stat_inc_inline_dir(inode);
-
-       f2fs_set_inode_flags(inode);
-
-       trace_f2fs_new_inode(inode, 0);
-       return inode;
-
-fail:
-       trace_f2fs_new_inode(inode, err);
-       make_bad_inode(inode);
-       if (nid_free)
-               set_inode_flag(inode, FI_FREE_NID);
-       iput(inode);
-       return ERR_PTR(err);
-fail_drop:
-       trace_f2fs_new_inode(inode, err);
-       dquot_drop(inode);
-       inode->i_flags |= S_NOQUOTA;
-       if (nid_free)
-               set_inode_flag(inode, FI_FREE_NID);
-       clear_nlink(inode);
-       unlock_new_inode(inode);
-       iput(inode);
-       return ERR_PTR(err);
-}
-
 static inline int is_extension_exist(const unsigned char *s, const char *sub,
                                                bool tmp_ext)
 {
@@ -187,36 +56,6 @@ static inline int is_extension_exist(const unsigned char *s, const char *sub,
        return 0;
 }
 
-/*
- * Set file's temperature for hot/cold data separation
- */
-static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode *inode,
-               const unsigned char *name)
-{
-       __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list;
-       int i, cold_count, hot_count;
-
-       f2fs_down_read(&sbi->sb_lock);
-
-       cold_count = le32_to_cpu(sbi->raw_super->extension_count);
-       hot_count = sbi->raw_super->hot_ext_count;
-
-       for (i = 0; i < cold_count + hot_count; i++) {
-               if (is_extension_exist(name, extlist[i], true))
-                       break;
-       }
-
-       f2fs_up_read(&sbi->sb_lock);
-
-       if (i == cold_count + hot_count)
-               return;
-
-       if (i < cold_count)
-               file_set_cold(inode);
-       else
-               file_set_hot(inode);
-}
-
 int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
                                                        bool hot, bool set)
 {
@@ -283,56 +122,215 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
        return 0;
 }
 
-static void set_compress_inode(struct f2fs_sb_info *sbi, struct inode *inode,
-                                               const unsigned char *name)
+static void set_compress_new_inode(struct f2fs_sb_info *sbi, struct inode *dir,
+                               struct inode *inode, const unsigned char *name)
 {
        __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list;
-       unsigned char (*noext)[F2FS_EXTENSION_LEN] = F2FS_OPTION(sbi).noextensions;
+       unsigned char (*noext)[F2FS_EXTENSION_LEN] =
+                                               F2FS_OPTION(sbi).noextensions;
        unsigned char (*ext)[F2FS_EXTENSION_LEN] = F2FS_OPTION(sbi).extensions;
        unsigned char ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt;
        unsigned char noext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt;
        int i, cold_count, hot_count;
 
-       if (!f2fs_sb_has_compression(sbi) ||
-                       F2FS_I(inode)->i_flags & F2FS_NOCOMP_FL ||
-                       !f2fs_may_compress(inode) ||
-                       (!ext_cnt && !noext_cnt))
+       if (!f2fs_sb_has_compression(sbi))
                return;
 
-       f2fs_down_read(&sbi->sb_lock);
+       if (S_ISDIR(inode->i_mode))
+               goto inherit_comp;
 
+       /* This name comes only from normal files. */
+       if (!name)
+               return;
+
+       /* Don't compress hot files. */
+       f2fs_down_read(&sbi->sb_lock);
        cold_count = le32_to_cpu(sbi->raw_super->extension_count);
        hot_count = sbi->raw_super->hot_ext_count;
+       for (i = cold_count; i < cold_count + hot_count; i++)
+               if (is_extension_exist(name, extlist[i], false))
+                       break;
+       f2fs_up_read(&sbi->sb_lock);
+       if (i < (cold_count + hot_count))
+               return;
+
+       /* Don't compress unallowed extension. */
+       for (i = 0; i < noext_cnt; i++)
+               if (is_extension_exist(name, noext[i], false))
+                       return;
 
-       for (i = cold_count; i < cold_count + hot_count; i++) {
-               if (is_extension_exist(name, extlist[i], false)) {
-                       f2fs_up_read(&sbi->sb_lock);
+       /* Compress wanting extension. */
+       for (i = 0; i < ext_cnt; i++) {
+               if (is_extension_exist(name, ext[i], false)) {
+                       set_compress_context(inode);
                        return;
                }
        }
+inherit_comp:
+       /* Inherit the {no-}compression flag in directory */
+       if (F2FS_I(dir)->i_flags & F2FS_NOCOMP_FL) {
+               F2FS_I(inode)->i_flags |= F2FS_NOCOMP_FL;
+               f2fs_mark_inode_dirty_sync(inode, true);
+       } else if (F2FS_I(dir)->i_flags & F2FS_COMPR_FL) {
+               set_compress_context(inode);
+       }
+}
+
+/*
+ * Set file's temperature for hot/cold data separation
+ */
+static void set_file_temperature(struct f2fs_sb_info *sbi, struct inode *inode,
+               const unsigned char *name)
+{
+       __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list;
+       int i, cold_count, hot_count;
 
+       f2fs_down_read(&sbi->sb_lock);
+       cold_count = le32_to_cpu(sbi->raw_super->extension_count);
+       hot_count = sbi->raw_super->hot_ext_count;
+       for (i = 0; i < cold_count + hot_count; i++)
+               if (is_extension_exist(name, extlist[i], true))
+                       break;
        f2fs_up_read(&sbi->sb_lock);
 
-       for (i = 0; i < noext_cnt; i++) {
-               if (is_extension_exist(name, noext[i], false)) {
-                       f2fs_disable_compressed_file(inode);
-                       return;
-               }
+       if (i == cold_count + hot_count)
+               return;
+
+       if (i < cold_count)
+               file_set_cold(inode);
+       else
+               file_set_hot(inode);
+}
+
+static struct inode *f2fs_new_inode(struct user_namespace *mnt_userns,
+                                               struct inode *dir, umode_t mode,
+                                               const char *name)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
+       nid_t ino;
+       struct inode *inode;
+       bool nid_free = false;
+       bool encrypt = false;
+       int xattr_size = 0;
+       int err;
+
+       inode = new_inode(dir->i_sb);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+
+       if (!f2fs_alloc_nid(sbi, &ino)) {
+               err = -ENOSPC;
+               goto fail;
        }
 
-       if (is_inode_flag_set(inode, FI_COMPRESSED_FILE))
-               return;
+       nid_free = true;
 
-       for (i = 0; i < ext_cnt; i++) {
-               if (!is_extension_exist(name, ext[i], false))
-                       continue;
+       inode_init_owner(mnt_userns, inode, dir, mode);
 
-               /* Do not use inline_data with compression */
-               stat_dec_inline_inode(inode);
-               clear_inode_flag(inode, FI_INLINE_DATA);
-               set_compress_context(inode);
-               return;
+       inode->i_ino = ino;
+       inode->i_blocks = 0;
+       inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+       F2FS_I(inode)->i_crtime = inode->i_mtime;
+       inode->i_generation = get_random_u32();
+
+       if (S_ISDIR(inode->i_mode))
+               F2FS_I(inode)->i_current_depth = 1;
+
+       err = insert_inode_locked(inode);
+       if (err) {
+               err = -EINVAL;
+               goto fail;
+       }
+
+       if (f2fs_sb_has_project_quota(sbi) &&
+               (F2FS_I(dir)->i_flags & F2FS_PROJINHERIT_FL))
+               F2FS_I(inode)->i_projid = F2FS_I(dir)->i_projid;
+       else
+               F2FS_I(inode)->i_projid = make_kprojid(mnt_userns,
+                                                       F2FS_DEF_PROJID);
+
+       err = fscrypt_prepare_new_inode(dir, inode, &encrypt);
+       if (err)
+               goto fail_drop;
+
+       err = f2fs_dquot_initialize(inode);
+       if (err)
+               goto fail_drop;
+
+       set_inode_flag(inode, FI_NEW_INODE);
+
+       if (encrypt)
+               f2fs_set_encrypted_inode(inode);
+
+       if (f2fs_sb_has_extra_attr(sbi)) {
+               set_inode_flag(inode, FI_EXTRA_ATTR);
+               F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;
+       }
+
+       if (test_opt(sbi, INLINE_XATTR))
+               set_inode_flag(inode, FI_INLINE_XATTR);
+
+       if (f2fs_may_inline_dentry(inode))
+               set_inode_flag(inode, FI_INLINE_DENTRY);
+
+       if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
+               f2fs_bug_on(sbi, !f2fs_has_extra_attr(inode));
+               if (f2fs_has_inline_xattr(inode))
+                       xattr_size = F2FS_OPTION(sbi).inline_xattr_size;
+               /* Otherwise, will be 0 */
+       } else if (f2fs_has_inline_xattr(inode) ||
+                               f2fs_has_inline_dentry(inode)) {
+               xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
        }
+       F2FS_I(inode)->i_inline_xattr_size = xattr_size;
+
+       F2FS_I(inode)->i_flags =
+               f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED);
+
+       if (S_ISDIR(inode->i_mode))
+               F2FS_I(inode)->i_flags |= F2FS_INDEX_FL;
+
+       if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL)
+               set_inode_flag(inode, FI_PROJ_INHERIT);
+
+       /* Check compression first. */
+       set_compress_new_inode(sbi, dir, inode, name);
+
+       /* Should enable inline_data after compression set */
+       if (test_opt(sbi, INLINE_DATA) && f2fs_may_inline_data(inode))
+               set_inode_flag(inode, FI_INLINE_DATA);
+
+       if (name && !test_opt(sbi, DISABLE_EXT_IDENTIFY))
+               set_file_temperature(sbi, inode, name);
+
+       stat_inc_inline_xattr(inode);
+       stat_inc_inline_inode(inode);
+       stat_inc_inline_dir(inode);
+
+       f2fs_set_inode_flags(inode);
+
+       f2fs_init_extent_tree(inode);
+
+       trace_f2fs_new_inode(inode, 0);
+       return inode;
+
+fail:
+       trace_f2fs_new_inode(inode, err);
+       make_bad_inode(inode);
+       if (nid_free)
+               set_inode_flag(inode, FI_FREE_NID);
+       iput(inode);
+       return ERR_PTR(err);
+fail_drop:
+       trace_f2fs_new_inode(inode, err);
+       dquot_drop(inode);
+       inode->i_flags |= S_NOQUOTA;
+       if (nid_free)
+               set_inode_flag(inode, FI_FREE_NID);
+       clear_nlink(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       return ERR_PTR(err);
 }
 
 static int f2fs_create(struct user_namespace *mnt_userns, struct inode *dir,
@@ -352,15 +350,10 @@ static int f2fs_create(struct user_namespace *mnt_userns, struct inode *dir,
        if (err)
                return err;
 
-       inode = f2fs_new_inode(mnt_userns, dir, mode);
+       inode = f2fs_new_inode(mnt_userns, dir, mode, dentry->d_name.name);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
-       if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
-               set_file_temperature(sbi, inode, dentry->d_name.name);
-
-       set_compress_inode(sbi, inode, dentry->d_name.name);
-
        inode->i_op = &f2fs_file_inode_operations;
        inode->i_fop = &f2fs_file_operations;
        inode->i_mapping->a_ops = &f2fs_dblock_aops;
@@ -632,6 +625,8 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
                goto fail;
        }
        f2fs_delete_entry(de, page, dir, inode);
+       f2fs_unlock_op(sbi);
+
 #if IS_ENABLED(CONFIG_UNICODE)
        /* VFS negative dentries are incompatible with Encoding and
         * Case-insensitiveness. Eventually we'll want avoid
@@ -642,8 +637,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
        if (IS_CASEFOLDED(dir))
                d_invalidate(dentry);
 #endif
-       f2fs_unlock_op(sbi);
-
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
 fail:
@@ -689,7 +682,7 @@ static int f2fs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
        if (err)
                return err;
 
-       inode = f2fs_new_inode(mnt_userns, dir, S_IFLNK | S_IRWXUGO);
+       inode = f2fs_new_inode(mnt_userns, dir, S_IFLNK | S_IRWXUGO, NULL);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
@@ -760,7 +753,7 @@ static int f2fs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
        if (err)
                return err;
 
-       inode = f2fs_new_inode(mnt_userns, dir, S_IFDIR | mode);
+       inode = f2fs_new_inode(mnt_userns, dir, S_IFDIR | mode, NULL);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
@@ -817,7 +810,7 @@ static int f2fs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
        if (err)
                return err;
 
-       inode = f2fs_new_inode(mnt_userns, dir, mode);
+       inode = f2fs_new_inode(mnt_userns, dir, mode, NULL);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
@@ -856,7 +849,7 @@ static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
        if (err)
                return err;
 
-       inode = f2fs_new_inode(mnt_userns, dir, mode);
+       inode = f2fs_new_inode(mnt_userns, dir, mode, NULL);
        if (IS_ERR(inode))
                return PTR_ERR(inode);