f2fs: use percpu_counter for # of dirty pages in inode
authorJaegeuk Kim <jaegeuk@kernel.org>
Fri, 13 May 2016 19:47:11 +0000 (12:47 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 18 May 2016 20:57:28 +0000 (13:57 -0700)
This patch adds percpu_counter for # of dirty pages in inode.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/super.c

index c2d0b24..3f1c710 100644 (file)
@@ -436,7 +436,7 @@ struct f2fs_inode_info {
        /* Use below internally in f2fs*/
        unsigned long flags;            /* use to pass per-file flags */
        struct rw_semaphore i_sem;      /* protect fi info */
-       atomic_t dirty_pages;           /* # of dirty pages */
+       struct percpu_counter dirty_pages;      /* # of dirty pages */
        f2fs_hash_t chash;              /* hash value of given file name */
        unsigned int clevel;            /* maximum level of given file name */
        nid_t i_xattr_nid;              /* node id that contains xattrs */
@@ -1166,7 +1166,7 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
 
 static inline void inode_inc_dirty_pages(struct inode *inode)
 {
-       atomic_inc(&F2FS_I(inode)->dirty_pages);
+       percpu_counter_inc(&F2FS_I(inode)->dirty_pages);
        inc_page_count(F2FS_I_SB(inode), S_ISDIR(inode->i_mode) ?
                                F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA);
 }
@@ -1182,7 +1182,7 @@ static inline void inode_dec_dirty_pages(struct inode *inode)
                        !S_ISLNK(inode->i_mode))
                return;
 
-       atomic_dec(&F2FS_I(inode)->dirty_pages);
+       percpu_counter_dec(&F2FS_I(inode)->dirty_pages);
        dec_page_count(F2FS_I_SB(inode), S_ISDIR(inode->i_mode) ?
                                F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA);
 }
@@ -1192,9 +1192,9 @@ static inline s64 get_pages(struct f2fs_sb_info *sbi, int count_type)
        return percpu_counter_sum_positive(&sbi->nr_pages[count_type]);
 }
 
-static inline int get_dirty_pages(struct inode *inode)
+static inline s64 get_dirty_pages(struct inode *inode)
 {
-       return atomic_read(&F2FS_I(inode)->dirty_pages);
+       return percpu_counter_sum_positive(&F2FS_I(inode)->dirty_pages);
 }
 
 static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
index a9cb314..69dd7c9 100644 (file)
@@ -1419,7 +1419,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
                goto out;
 
        f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
-               "Unexpected flush for atomic writes: ino=%lu, npages=%u",
+               "Unexpected flush for atomic writes: ino=%lu, npages=%lld",
                                        inode->i_ino, get_dirty_pages(inode));
        ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
        if (ret)
index 009a9f4..0ff862b 100644 (file)
@@ -526,9 +526,13 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 
        init_once((void *) fi);
 
+       if (percpu_counter_init(&fi->dirty_pages, 0, GFP_NOFS)) {
+               kmem_cache_free(f2fs_inode_cachep, fi);
+               return NULL;
+       }
+
        /* Initialize f2fs-specific inode info */
        fi->vfs_inode.i_version = 1;
-       atomic_set(&fi->dirty_pages, 0);
        fi->i_current_depth = 1;
        fi->i_advise = 0;
        init_rwsem(&fi->i_sem);
@@ -603,6 +607,7 @@ static void f2fs_i_callback(struct rcu_head *head)
 
 static void f2fs_destroy_inode(struct inode *inode)
 {
+       percpu_counter_destroy(&F2FS_I(inode)->dirty_pages);
        call_rcu(&inode->i_rcu, f2fs_i_callback);
 }