]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/f2fs/namei.c
Merge tag 'tag-chrome-platform-for-v5.6' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / fs / f2fs / namei.c
index 5d9584281935fa9290906f3bef89fe705675ad2d..2aa035422c0fac63a51e60d1a5dce93a37482dc6 100644 (file)
@@ -119,6 +119,13 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
        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);
+       }
+
        f2fs_set_inode_flags(inode);
 
        trace_f2fs_new_inode(inode, 0);
@@ -149,6 +156,9 @@ static inline int is_extension_exist(const unsigned char *s, const char *sub)
        size_t sublen = strlen(sub);
        int i;
 
+       if (sublen == 1 && *sub == '*')
+               return 1;
+
        /*
         * filename format of multimedia file should be defined as:
         * "filename + '.' + extension + (optional: '.' + temp extension)".
@@ -262,6 +272,45 @@ 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)
+{
+       __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list;
+       unsigned char (*ext)[F2FS_EXTENSION_LEN];
+       unsigned int ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt;
+       int i, cold_count, hot_count;
+
+       if (!f2fs_sb_has_compression(sbi) ||
+                       is_inode_flag_set(inode, FI_COMPRESSED_FILE) ||
+                       F2FS_I(inode)->i_flags & F2FS_NOCOMP_FL ||
+                       !f2fs_may_compress(inode))
+               return;
+
+       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])) {
+                       up_read(&sbi->sb_lock);
+                       return;
+               }
+       }
+
+       up_read(&sbi->sb_lock);
+
+       ext = F2FS_OPTION(sbi).extensions;
+
+       for (i = 0; i < ext_cnt; i++) {
+               if (!is_extension_exist(name, ext[i]))
+                       continue;
+
+               set_compress_context(inode);
+               return;
+       }
+}
+
 static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                                                bool excl)
 {
@@ -286,6 +335,8 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        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;
@@ -850,12 +901,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct inode *old_inode = d_inode(old_dentry);
        struct inode *new_inode = d_inode(new_dentry);
        struct inode *whiteout = NULL;
-       struct page *old_dir_page;
+       struct page *old_dir_page = NULL;
        struct page *old_page, *new_page = NULL;
        struct f2fs_dir_entry *old_dir_entry = NULL;
        struct f2fs_dir_entry *old_entry;
        struct f2fs_dir_entry *new_entry;
-       bool is_old_inline = f2fs_has_inline_dentry(old_dir);
        int err;
 
        if (unlikely(f2fs_cp_error(sbi)))
@@ -868,6 +918,20 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        F2FS_I(old_dentry->d_inode)->i_projid)))
                return -EXDEV;
 
+       /*
+        * If new_inode is null, the below renaming flow will
+        * add a link in old_dir which can conver inline_dir.
+        * After then, if we failed to get the entry due to other
+        * reasons like ENOMEM, we had to remove the new entry.
+        * Instead of adding such the error handling routine, let's
+        * simply convert first here.
+        */
+       if (old_dir == new_dir && !new_inode) {
+               err = f2fs_try_convert_inline_dir(old_dir, new_dentry);
+               if (err)
+                       return err;
+       }
+
        if (flags & RENAME_WHITEOUT) {
                err = f2fs_create_whiteout(old_dir, &whiteout);
                if (err)
@@ -929,6 +993,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        goto put_out_dir;
 
                f2fs_set_link(new_dir, new_entry, new_page, old_inode);
+               new_page = NULL;
 
                new_inode->i_ctime = current_time(new_inode);
                down_write(&F2FS_I(new_inode)->i_sem);
@@ -954,28 +1019,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
                if (old_dir_entry)
                        f2fs_i_links_write(new_dir, true);
-
-               /*
-                * old entry and new entry can locate in the same inline
-                * dentry in inode, when attaching new entry in inline dentry,
-                * it could force inline dentry conversion, after that,
-                * old_entry and old_page will point to wrong address, in
-                * order to avoid this, let's do the check and update here.
-                */
-               if (is_old_inline && !f2fs_has_inline_dentry(old_dir)) {
-                       f2fs_put_page(old_page, 0);
-                       old_page = NULL;
-
-                       old_entry = f2fs_find_entry(old_dir,
-                                               &old_dentry->d_name, &old_page);
-                       if (!old_entry) {
-                               err = -ENOENT;
-                               if (IS_ERR(old_page))
-                                       err = PTR_ERR(old_page);
-                               f2fs_unlock_op(sbi);
-                               goto out_dir;
-                       }
-               }
        }
 
        down_write(&F2FS_I(old_inode)->i_sem);
@@ -990,6 +1033,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
        f2fs_mark_inode_dirty_sync(old_inode, false);
 
        f2fs_delete_entry(old_entry, old_page, old_dir, NULL);
+       old_page = NULL;
 
        if (whiteout) {
                set_inode_flag(whiteout, FI_INC_LINK);
@@ -1025,8 +1069,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 put_out_dir:
        f2fs_unlock_op(sbi);
-       if (new_page)
-               f2fs_put_page(new_page, 0);
+       f2fs_put_page(new_page, 0);
 out_dir:
        if (old_dir_entry)
                f2fs_put_page(old_dir_page, 0);