Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
[linux-2.6-microblaze.git] / fs / f2fs / super.c
index 55203f6..1b86d3f 100644 (file)
@@ -49,6 +49,7 @@ char *fault_name[FAULT_MAX] = {
        [FAULT_ORPHAN]          = "orphan",
        [FAULT_BLOCK]           = "no more block",
        [FAULT_DIR_DEPTH]       = "too big dir depth",
+       [FAULT_EVICT_INODE]     = "evict_inode fail",
 };
 
 static void f2fs_build_fault_attr(unsigned int rate)
@@ -75,6 +76,7 @@ enum {
        Opt_disable_roll_forward,
        Opt_norecovery,
        Opt_discard,
+       Opt_nodiscard,
        Opt_noheap,
        Opt_user_xattr,
        Opt_nouser_xattr,
@@ -93,6 +95,7 @@ enum {
        Opt_noextent_cache,
        Opt_noinline_data,
        Opt_data_flush,
+       Opt_mode,
        Opt_fault_injection,
        Opt_lazytime,
        Opt_nolazytime,
@@ -104,6 +107,7 @@ static match_table_t f2fs_tokens = {
        {Opt_disable_roll_forward, "disable_roll_forward"},
        {Opt_norecovery, "norecovery"},
        {Opt_discard, "discard"},
+       {Opt_nodiscard, "nodiscard"},
        {Opt_noheap, "no_heap"},
        {Opt_user_xattr, "user_xattr"},
        {Opt_nouser_xattr, "nouser_xattr"},
@@ -122,6 +126,7 @@ static match_table_t f2fs_tokens = {
        {Opt_noextent_cache, "noextent_cache"},
        {Opt_noinline_data, "noinline_data"},
        {Opt_data_flush, "data_flush"},
+       {Opt_mode, "mode=%s"},
        {Opt_fault_injection, "fault_injection=%u"},
        {Opt_lazytime, "lazytime"},
        {Opt_nolazytime, "nolazytime"},
@@ -423,6 +428,8 @@ static int parse_options(struct super_block *sb, char *options)
                                        "the device does not support discard");
                        }
                        break;
+               case Opt_nodiscard:
+                       clear_opt(sbi, DISCARD);
                case Opt_noheap:
                        set_opt(sbi, NOHEAP);
                        break;
@@ -505,6 +512,23 @@ static int parse_options(struct super_block *sb, char *options)
                case Opt_data_flush:
                        set_opt(sbi, DATA_FLUSH);
                        break;
+               case Opt_mode:
+                       name = match_strdup(&args[0]);
+
+                       if (!name)
+                               return -ENOMEM;
+                       if (strlen(name) == 8 &&
+                                       !strncmp(name, "adaptive", 8)) {
+                               set_opt_mode(sbi, F2FS_MOUNT_ADAPTIVE);
+                       } else if (strlen(name) == 3 &&
+                                       !strncmp(name, "lfs", 3)) {
+                               set_opt_mode(sbi, F2FS_MOUNT_LFS);
+                       } else {
+                               kfree(name);
+                               return -EINVAL;
+                       }
+                       kfree(name);
+                       break;
                case Opt_fault_injection:
                        if (args->from && match_int(args, &arg))
                                return -EINVAL;
@@ -555,6 +579,8 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
        INIT_LIST_HEAD(&fi->gdirty_list);
        INIT_LIST_HEAD(&fi->inmem_pages);
        mutex_init(&fi->inmem_lock);
+       init_rwsem(&fi->dio_rwsem[READ]);
+       init_rwsem(&fi->dio_rwsem[WRITE]);
 
        /* Will be used by directory only */
        fi->i_dir_level = F2FS_SB(sb)->dir_level;
@@ -563,8 +589,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 
 static int f2fs_drop_inode(struct inode *inode)
 {
-       int ret;
-
        /*
         * This is to avoid a deadlock condition like below.
         * writeback_single_inode(inode)
@@ -589,7 +613,7 @@ static int f2fs_drop_inode(struct inode *inode)
                        f2fs_i_size_write(inode, 0);
 
                        if (F2FS_HAS_BLOCKS(inode))
-                               f2fs_truncate(inode, true);
+                               f2fs_truncate(inode);
 
                        sb_end_intwrite(inode->i_sb);
 
@@ -600,52 +624,27 @@ static int f2fs_drop_inode(struct inode *inode)
                return 0;
        }
 
-       ret = generic_drop_inode(inode);
-       if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
-               if (ret)
-                       inode->i_state |= I_WILL_FREE;
-               spin_unlock(&inode->i_lock);
-
-               update_inode_page(inode);
-
-               spin_lock(&inode->i_lock);
-               if (ret)
-                       inode->i_state &= ~I_WILL_FREE;
-       }
-       return ret;
+       return generic_drop_inode(inode);
 }
 
-/*
- * f2fs_dirty_inode() is called from __mark_inode_dirty()
- *
- * We should call set_dirty_inode to write the dirty inode through write_inode.
- */
-static void f2fs_dirty_inode(struct inode *inode, int flags)
+int f2fs_inode_dirtied(struct inode *inode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 
-       if (inode->i_ino == F2FS_NODE_INO(sbi) ||
-                       inode->i_ino == F2FS_META_INO(sbi))
-               return;
-
-       if (flags == I_DIRTY_TIME)
-               return;
-
-       if (is_inode_flag_set(inode, FI_AUTO_RECOVER))
-               clear_inode_flag(inode, FI_AUTO_RECOVER);
-
        spin_lock(&sbi->inode_lock[DIRTY_META]);
        if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
                spin_unlock(&sbi->inode_lock[DIRTY_META]);
-               return;
+               return 1;
        }
 
        set_inode_flag(inode, FI_DIRTY_INODE);
        list_add_tail(&F2FS_I(inode)->gdirty_list,
                                &sbi->inode_list[DIRTY_META]);
        inc_page_count(sbi, F2FS_DIRTY_IMETA);
-       spin_unlock(&sbi->inode_lock[DIRTY_META]);
        stat_inc_dirty_inode(sbi, DIRTY_META);
+       spin_unlock(&sbi->inode_lock[DIRTY_META]);
+
+       return 0;
 }
 
 void f2fs_inode_synced(struct inode *inode)
@@ -661,8 +660,30 @@ void f2fs_inode_synced(struct inode *inode)
        clear_inode_flag(inode, FI_DIRTY_INODE);
        clear_inode_flag(inode, FI_AUTO_RECOVER);
        dec_page_count(sbi, F2FS_DIRTY_IMETA);
-       spin_unlock(&sbi->inode_lock[DIRTY_META]);
        stat_dec_dirty_inode(F2FS_I_SB(inode), DIRTY_META);
+       spin_unlock(&sbi->inode_lock[DIRTY_META]);
+}
+
+/*
+ * f2fs_dirty_inode() is called from __mark_inode_dirty()
+ *
+ * We should call set_dirty_inode to write the dirty inode through write_inode.
+ */
+static void f2fs_dirty_inode(struct inode *inode, int flags)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+
+       if (inode->i_ino == F2FS_NODE_INO(sbi) ||
+                       inode->i_ino == F2FS_META_INO(sbi))
+               return;
+
+       if (flags == I_DIRTY_TIME)
+               return;
+
+       if (is_inode_flag_set(inode, FI_AUTO_RECOVER))
+               clear_inode_flag(inode, FI_AUTO_RECOVER);
+
+       f2fs_inode_dirtied(inode);
 }
 
 static void f2fs_i_callback(struct rcu_head *head)
@@ -685,6 +706,8 @@ static void destroy_percpu_info(struct f2fs_sb_info *sbi)
                percpu_counter_destroy(&sbi->nr_pages[i]);
        percpu_counter_destroy(&sbi->alloc_valid_block_count);
        percpu_counter_destroy(&sbi->total_valid_inode_count);
+
+       percpu_free_rwsem(&sbi->cp_rwsem);
 }
 
 static void f2fs_put_super(struct super_block *sb)
@@ -804,7 +827,7 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_bsize = sbi->blocksize;
 
        buf->f_blocks = total_count - start_count;
-       buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;
+       buf->f_bfree = user_block_count - valid_user_blocks(sbi) + ovp_count;
        buf->f_bavail = user_block_count - valid_user_blocks(sbi);
 
        buf->f_files = sbi->total_node_count - F2FS_RESERVED_NODE_NUM;
@@ -869,6 +892,12 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
                seq_puts(seq, ",noextent_cache");
        if (test_opt(sbi, DATA_FLUSH))
                seq_puts(seq, ",data_flush");
+
+       seq_puts(seq, ",mode=");
+       if (test_opt(sbi, ADAPTIVE))
+               seq_puts(seq, "adaptive");
+       else if (test_opt(sbi, LFS))
+               seq_puts(seq, "lfs");
        seq_printf(seq, ",active_logs=%u", sbi->active_logs);
 
        return 0;
@@ -932,7 +961,6 @@ static int _name##_open_fs(struct inode *inode, struct file *file)  \
 }                                                                      \
                                                                        \
 static const struct file_operations f2fs_seq_##_name##_fops = {                \
-       .owner = THIS_MODULE,                                           \
        .open = _name##_open_fs,                                        \
        .read = seq_read,                                               \
        .llseek = seq_lseek,                                            \
@@ -952,6 +980,12 @@ static void default_options(struct f2fs_sb_info *sbi)
        set_opt(sbi, EXTENT_CACHE);
        sbi->sb->s_flags |= MS_LAZYTIME;
        set_opt(sbi, FLUSH_MERGE);
+       if (f2fs_sb_mounted_hmsmr(sbi->sb)) {
+               set_opt_mode(sbi, F2FS_MOUNT_LFS);
+               set_opt(sbi, DISCARD);
+       } else {
+               set_opt_mode(sbi, F2FS_MOUNT_ADAPTIVE);
+       }
 
 #ifdef CONFIG_F2FS_FS_XATTR
        set_opt(sbi, XATTR_USER);
@@ -1435,6 +1469,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
 
        INIT_LIST_HEAD(&sbi->s_list);
        mutex_init(&sbi->umount_mutex);
+       mutex_init(&sbi->wio_mutex[NODE]);
+       mutex_init(&sbi->wio_mutex[DATA]);
 
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
        memcpy(sbi->key_prefix, F2FS_KEY_DESC_PREFIX,
@@ -1447,6 +1483,9 @@ static int init_percpu_info(struct f2fs_sb_info *sbi)
 {
        int i, err;
 
+       if (percpu_init_rwsem(&sbi->cp_rwsem))
+               return -ENOMEM;
+
        for (i = 0; i < NR_COUNT_TYPE; i++) {
                err = percpu_counter_init(&sbi->nr_pages[i], 0, GFP_KERNEL);
                if (err)
@@ -1598,6 +1637,8 @@ try_onemore:
                goto free_sbi;
 
        sb->s_fs_info = sbi;
+       sbi->raw_super = raw_super;
+
        default_options(sbi);
        /* parse mount options */
        options = kstrdup((const char *)data, GFP_KERNEL);
@@ -1627,10 +1668,8 @@ try_onemore:
        memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));
 
        /* init f2fs-specific super block info */
-       sbi->raw_super = raw_super;
        sbi->valid_super_block = valid_super_block;
        mutex_init(&sbi->gc_mutex);
-       mutex_init(&sbi->writepages);
        mutex_init(&sbi->cp_mutex);
        init_rwsem(&sbi->node_write);
 
@@ -1647,7 +1686,6 @@ try_onemore:
                sbi->write_io[i].bio = NULL;
        }
 
-       init_rwsem(&sbi->cp_rwsem);
        init_waitqueue_head(&sbi->cp_wait);
        init_sb_info(sbi);