f2fs: use extent_cache by default
[deliverable/linux.git] / fs / f2fs / super.c
index a06b0b46fe6952de875dc36b0c4e90c0ce980c31..0083b8559c9b03ff5d1ec8b7ecd556c751bbda20 100644 (file)
@@ -39,6 +39,13 @@ static struct proc_dir_entry *f2fs_proc_root;
 static struct kmem_cache *f2fs_inode_cachep;
 static struct kset *f2fs_kset;
 
+/* f2fs-wide shrinker description */
+static struct shrinker f2fs_shrinker_info = {
+       .scan_objects = f2fs_shrink_scan,
+       .count_objects = f2fs_shrink_count,
+       .seeks = DEFAULT_SEEKS,
+};
+
 enum {
        Opt_gc_background,
        Opt_disable_roll_forward,
@@ -58,6 +65,7 @@ enum {
        Opt_nobarrier,
        Opt_fastboot,
        Opt_extent_cache,
+       Opt_noextent_cache,
        Opt_noinline_data,
        Opt_err,
 };
@@ -81,6 +89,7 @@ static match_table_t f2fs_tokens = {
        {Opt_nobarrier, "nobarrier"},
        {Opt_fastboot, "fastboot"},
        {Opt_extent_cache, "extent_cache"},
+       {Opt_noextent_cache, "noextent_cache"},
        {Opt_noinline_data, "noinline_data"},
        {Opt_err, NULL},
 };
@@ -382,6 +391,9 @@ static int parse_options(struct super_block *sb, char *options)
                case Opt_extent_cache:
                        set_opt(sbi, EXTENT_CACHE);
                        break;
+               case Opt_noextent_cache:
+                       clear_opt(sbi, EXTENT_CACHE);
+                       break;
                case Opt_noinline_data:
                        clear_opt(sbi, INLINE_DATA);
                        break;
@@ -410,7 +422,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
        atomic_set(&fi->dirty_pages, 0);
        fi->i_current_depth = 1;
        fi->i_advise = 0;
-       rwlock_init(&fi->ext_lock);
        init_rwsem(&fi->i_sem);
        INIT_RADIX_TREE(&fi->inmem_root, GFP_NOFS);
        INIT_LIST_HEAD(&fi->inmem_pages);
@@ -441,12 +452,17 @@ static int f2fs_drop_inode(struct inode *inode)
         */
        if (!inode_unhashed(inode) && inode->i_state & I_SYNC) {
                if (!inode->i_nlink && !is_bad_inode(inode)) {
+                       /* to avoid evict_inode call simultaneously */
+                       atomic_inc(&inode->i_count);
                        spin_unlock(&inode->i_lock);
 
                        /* some remained atomic pages should discarded */
                        if (f2fs_is_atomic_file(inode))
                                commit_inmem_pages(inode, true);
 
+                       /* should remain fi->extent_tree for writepage */
+                       f2fs_destroy_extent_node(inode);
+
                        sb_start_intwrite(inode->i_sb);
                        i_size_write(inode, 0);
 
@@ -461,6 +477,7 @@ static int f2fs_drop_inode(struct inode *inode)
                                        F2FS_I(inode)->i_crypt_info);
 #endif
                        spin_lock(&inode->i_lock);
+                       atomic_dec(&inode->i_count);
                }
                return 0;
        }
@@ -498,9 +515,11 @@ static void f2fs_put_super(struct super_block *sb)
        }
        kobject_del(&sbi->s_kobj);
 
-       f2fs_destroy_stats(sbi);
        stop_gc_thread(sbi);
 
+       /* prevent remaining shrinker jobs */
+       mutex_lock(&sbi->umount_mutex);
+
        /*
         * We don't need to do checkpoint when superblock is clean.
         * But, the previous checkpoint was not done by umount, it needs to do
@@ -514,6 +533,9 @@ static void f2fs_put_super(struct super_block *sb)
                write_checkpoint(sbi, &cpc);
        }
 
+       /* write_checkpoint can update stat informaion */
+       f2fs_destroy_stats(sbi);
+
        /*
         * normally superblock is clean, so we need to release this.
         * In addition, EIO will skip do checkpoint, we need this as well.
@@ -521,6 +543,9 @@ static void f2fs_put_super(struct super_block *sb)
        release_dirty_inode(sbi);
        release_discard_addrs(sbi);
 
+       f2fs_leave_shrinker(sbi);
+       mutex_unlock(&sbi->umount_mutex);
+
        iput(sbi->node_inode);
        iput(sbi->meta_inode);
 
@@ -647,6 +672,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
                seq_puts(seq, ",fastboot");
        if (test_opt(sbi, EXTENT_CACHE))
                seq_puts(seq, ",extent_cache");
+       else
+               seq_puts(seq, ",noextent_cache");
        seq_printf(seq, ",active_logs=%u", sbi->active_logs);
 
        return 0;
@@ -699,6 +726,7 @@ static void default_options(struct f2fs_sb_info *sbi)
 
        set_opt(sbi, BG_GC);
        set_opt(sbi, INLINE_DATA);
+       set_opt(sbi, EXTENT_CACHE);
 
 #ifdef CONFIG_F2FS_FS_XATTR
        set_opt(sbi, XATTR_USER);
@@ -970,6 +998,9 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
 
        sbi->dir_level = DEF_DIR_LEVEL;
        clear_sbi_flag(sbi, SBI_NEED_FSCK);
+
+       INIT_LIST_HEAD(&sbi->s_list);
+       mutex_init(&sbi->umount_mutex);
 }
 
 /*
@@ -1212,6 +1243,8 @@ try_onemore:
                goto free_nm;
        }
 
+       f2fs_join_shrinker(sbi);
+
        /* if there are nt orphan nodes free them */
        recover_orphan_inodes(sbi);
 
@@ -1308,7 +1341,10 @@ free_root_inode:
        dput(sb->s_root);
        sb->s_root = NULL;
 free_node_inode:
+       mutex_lock(&sbi->umount_mutex);
+       f2fs_leave_shrinker(sbi);
        iput(sbi->node_inode);
+       mutex_unlock(&sbi->umount_mutex);
 free_nm:
        destroy_node_manager(sbi);
 free_sm:
@@ -1404,13 +1440,20 @@ static int __init init_f2fs_fs(void)
        err = f2fs_init_crypto();
        if (err)
                goto free_kset;
-       err = register_filesystem(&f2fs_fs_type);
+
+       err = register_shrinker(&f2fs_shrinker_info);
        if (err)
                goto free_crypto;
+
+       err = register_filesystem(&f2fs_fs_type);
+       if (err)
+               goto free_shrinker;
        f2fs_create_root_stats();
        f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
        return 0;
 
+free_shrinker:
+       unregister_shrinker(&f2fs_shrinker_info);
 free_crypto:
        f2fs_exit_crypto();
 free_kset:
@@ -1433,6 +1476,7 @@ static void __exit exit_f2fs_fs(void)
 {
        remove_proc_entry("fs/f2fs", NULL);
        f2fs_destroy_root_stats();
+       unregister_shrinker(&f2fs_shrinker_info);
        unregister_filesystem(&f2fs_fs_type);
        f2fs_exit_crypto();
        destroy_extent_cache();
This page took 0.039822 seconds and 5 git commands to generate.