Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
[deliverable/linux.git] / fs / f2fs / super.c
index edc736de8ee950460e9fb0eeb83a8c44c674ca5e..b97c065cbe744b1eed931e3dd5754d8815ef3e6c 100644 (file)
@@ -76,6 +76,7 @@ enum {
        Opt_disable_roll_forward,
        Opt_norecovery,
        Opt_discard,
+       Opt_nodiscard,
        Opt_noheap,
        Opt_user_xattr,
        Opt_nouser_xattr,
@@ -106,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"},
@@ -426,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;
@@ -515,12 +519,10 @@ static int parse_options(struct super_block *sb, char *options)
                                return -ENOMEM;
                        if (strlen(name) == 8 &&
                                        !strncmp(name, "adaptive", 8)) {
-                               set_opt(sbi, ADAPTIVE);
-                               clear_opt(sbi, LFS);
+                               set_opt_mode(sbi, F2FS_MOUNT_ADAPTIVE);
                        } else if (strlen(name) == 3 &&
                                        !strncmp(name, "lfs", 3)) {
-                               clear_opt(sbi, ADAPTIVE);
-                               set_opt(sbi, LFS);
+                               set_opt_mode(sbi, F2FS_MOUNT_LFS);
                        } else {
                                kfree(name);
                                return -EINVAL;
@@ -577,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;
@@ -585,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)
@@ -622,44 +624,17 @@ 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);
@@ -668,6 +643,8 @@ static void f2fs_dirty_inode(struct inode *inode, int flags)
        inc_page_count(sbi, F2FS_DIRTY_IMETA);
        stat_inc_dirty_inode(sbi, DIRTY_META);
        spin_unlock(&sbi->inode_lock[DIRTY_META]);
+
+       return 0;
 }
 
 void f2fs_inode_synced(struct inode *inode)
@@ -687,6 +664,28 @@ void f2fs_inode_synced(struct inode *inode)
        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)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
@@ -707,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)
@@ -826,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;
@@ -980,7 +981,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);
-       set_opt(sbi, ADAPTIVE);
+       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);
@@ -1478,6 +1484,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)
@@ -1629,6 +1638,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);
@@ -1658,7 +1669,6 @@ 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->cp_mutex);
@@ -1677,7 +1687,6 @@ try_onemore:
                sbi->write_io[i].bio = NULL;
        }
 
-       init_rwsem(&sbi->cp_rwsem);
        init_waitqueue_head(&sbi->cp_wait);
        init_sb_info(sbi);
 
This page took 0.036942 seconds and 5 git commands to generate.