f2fs: manipulate dirty file inodes when DATA_FLUSH is set
Subsystems (2)
Jaegeuk Kim
maintainerPATCH 1/5 f2fs: manipulate dirty file inodes when DATA_FLUSH is set
It needs to maintain dirty file inodes only if DATA_FLUSH is set. Otherwise, let's avoid its overhead.
Signed-off-by Jaegeuk Kim <[email protected]>
--- fs/f2fs/checkpoint.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
fs/f2fs/checkpoint.c +8 -3
@@ -785,9 +785,11 @@ void update_dirty_page(struct inode *inode, struct page *page) !S_ISLNK(inode->i_mode))return ; -spin_lock (&sbi->inode_lock[type]); -__add_dirty_inode (inode, type); -spin_unlock (&sbi->inode_lock[type]); +if (type !=FILE_INODE ||test_opt (sbi,DATA_FLUSH )) { +spin_lock (&sbi->inode_lock[type]); +__add_dirty_inode (inode, type); +spin_unlock (&sbi->inode_lock[type]); + }inode_inc_dirty_pages (inode);SetPagePrivate (page);
@@ -803,6 +805,9 @@ void remove_dirty_inode(struct inode *inode) !S_ISLNK(inode->i_mode))return ; +if (type ==FILE_INODE && !test_opt (sbi,DATA_FLUSH )) +return ; +spin_lock (&sbi->inode_lock[type]);__remove_dirty_inode (inode, type);spin_unlock (&sbi->inode_lock[type]);
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 2/5 f2fs: use percpu_counter for page counters
This patch substitutes percpu_counter for atomic_counter when counting various types of pages.
Signed-off-by Jaegeuk Kim <[email protected]>
--- fs/f2fs/debug.c | 1 + fs/f2fs/f2fs.h | 12 +++++++----- fs/f2fs/super.c | 31 +++++++++++++++++++++++++++---- 3 files changed, 35 insertions(+), 9 deletions(-)
fs/f2fs/debug.c +1 -0
@@ -144,6 +144,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi) si->base_mem =sizeof (struct f2fs_sb_info ) + sbi->sb->s_blocksize; si->base_mem +=2 *sizeof (struct f2fs_inode_info ); si->base_mem +=sizeof (*sbi->ckpt); + si->base_mem +=sizeof (struct percpu_counter ) *NR_COUNT_TYPE ;/* build sm */ si->base_mem +=sizeof (struct f2fs_sm_info );
fs/f2fs/f2fs.h +7 -5
@@ -833,7 +833,9 @@ struct f2fs_sb_info {block_t discard_blks;/* discard command candidats */ block_t last_valid_block_count;/* for recovery */ u32 s_next_generation;/* for NFS support */ -atomic_t nr_pages[NR_COUNT_TYPE ];/* # of pages, see count_type */ + +/* # of pages, see count_type */ +struct percpu_counter nr_pages[NR_COUNT_TYPE ];struct f2fs_mount_info mount_opt;/* mount options */
@@ -1178,7 +1180,7 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,static inline void inc_page_count (struct f2fs_sb_info *sbi,int count_type) { -atomic_inc (&sbi->nr_pages[count_type]); +percpu_counter_inc (&sbi->nr_pages[count_type]);set_sbi_flag (sbi,SBI_IS_DIRTY ); }
@@ -1191,7 +1193,7 @@ static inline void inode_inc_dirty_pages(struct inode *inode)static inline void dec_page_count (struct f2fs_sb_info *sbi,int count_type) { -atomic_dec (&sbi->nr_pages[count_type]); +percpu_counter_dec (&sbi->nr_pages[count_type]); }static inline void inode_dec_dirty_pages (struct inode *inode)
@@ -1205,9 +1207,9 @@ static inline void inode_dec_dirty_pages(struct inode *inode) F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA); } -static inline int get_pages (struct f2fs_sb_info *sbi,int count_type) +static inline s64 get_pages (struct f2fs_sb_info *sbi,int count_type) { -return atomic_read (&sbi->nr_pages[count_type]); +return percpu_counter_sum_positive (&sbi->nr_pages[count_type]); }static inline int get_dirty_pages (struct inode *inode)
fs/f2fs/super.c +27 -4
@@ -606,6 +606,14 @@ static void f2fs_destroy_inode(struct inode *inode)call_rcu (&inode->i_rcu, f2fs_i_callback); } +static void destroy_percpu_info (struct f2fs_sb_info *sbi) +{ +int i; + +for (i =0 ; i <NR_COUNT_TYPE ; i++) +percpu_counter_destroy (&sbi->nr_pages[i]); +} +static void f2fs_put_super (struct super_block *sb) {struct f2fs_sb_info *sbi =F2FS_SB (sb);
@@ -667,6 +675,8 @@ static void f2fs_put_super(struct super_block *sb)if (sbi->s_chksum_driver)crypto_free_shash (sbi->s_chksum_driver);kfree (sbi->raw_super); + +destroy_percpu_info (sbi);kfree (sbi); }
@@ -1325,7 +1335,6 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi)static void init_sb_info (struct f2fs_sb_info *sbi) {struct f2fs_super_block *raw_super = sbi->raw_super; -int i; sbi->log_sectors_per_block =le32_to_cpu (raw_super->log_sectors_per_block);
@@ -1345,9 +1354,6 @@ static void init_sb_info(struct f2fs_sb_info *sbi) sbi->cur_victim_sec =NULL_SECNO ; sbi->max_victim_search =DEF_MAX_VICTIM_SEARCH ; -for (i =0 ; i <NR_COUNT_TYPE ; i++) -atomic_set (&sbi->nr_pages[i],0 ); - sbi->dir_level =DEF_DIR_LEVEL ; sbi->interval_time[CP_TIME ] =DEF_CP_INTERVAL ; sbi->interval_time[REQ_TIME ] =DEF_IDLE_INTERVAL ;
@@ -1363,6 +1369,18 @@ static void init_sb_info(struct f2fs_sb_info *sbi)#endif } +static int init_percpu_info (struct f2fs_sb_info *sbi) +{ +int i, err; + +for (i =0 ; i <NR_COUNT_TYPE ; i++) { + err =percpu_counter_init (&sbi->nr_pages[i],0 ,GFP_KERNEL ); +if (err) +return err; + } +return 0 ; +} +/* * Read f2fs raw super block. * Because we have two copies of super block, so read both of them
@@ -1553,6 +1571,10 @@ try_onemore:init_waitqueue_head (&sbi->cp_wait);init_sb_info (sbi); + err =init_percpu_info (sbi); +if (err) + goto free_options; +/* get an inode for meta space */ sbi->meta_inode =f2fs_iget (sb,F2FS_META_INO (sbi));if (IS_ERR (sbi->meta_inode)) {
@@ -1755,6 +1777,7 @@ free_meta_inode:make_bad_inode (sbi->meta_inode);iput (sbi->meta_inode); free_options: +destroy_percpu_info (sbi);kfree (options); free_sb_buf:kfree (raw_super);
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 3/5 f2fs: use percpu_counter for # of dirty pages in inode
In reply to Jaegeuk KimThis patch adds percpu_counter for # of dirty pages in inode.
Signed-off-by Jaegeuk Kim <[email protected]>
--- fs/f2fs/f2fs.h | 10 +++++----- fs/f2fs/file.c | 2 +- fs/f2fs/super.c | 8 +++++++- 3 files changed, 13 insertions(+), 7 deletions(-)
fs/f2fs/f2fs.h +5 -5
@@ -456,7 +456,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 */
@@ -1186,7 +1186,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 ); }
@@ -1202,7 +1202,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 ); }
@@ -1212,9 +1212,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)
fs/f2fs/file.c +1 -1
@@ -1457,7 +1457,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)
fs/f2fs/super.c +7 -1
@@ -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);
@@ -598,6 +602,8 @@ static void f2fs_dirty_inode(struct inode *inode, int flags)static void f2fs_i_callback (struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); + +percpu_counter_destroy (&F2FS_I (inode)->dirty_pages);kmem_cache_free (f2fs_inode_cachep,F2FS_I (inode)); }
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 4/5 f2fs: use percpu_counter for alloc_valid_block_count
In reply to Jaegeuk KimThis patch uses percpu_count for sbi->alloc_valid_block_count.
Signed-off-by Jaegeuk Kim <[email protected]>
--- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 8 +++++--- fs/f2fs/recovery.c | 5 +++-- fs/f2fs/super.c | 7 +++++-- 4 files changed, 14 insertions(+), 8 deletions(-)
fs/f2fs/checkpoint.c +1 -1
@@ -1079,7 +1079,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)/* update user_block_counts */ sbi->last_valid_block_count = sbi->total_valid_block_count; - sbi->alloc_valid_block_count =0 ; +percpu_counter_set (&sbi->alloc_valid_block_count,0 );/* Here, we only have one bio having CP pack */ sync_meta_pages (sbi,META_FLUSH ,LONG_MAX );
fs/f2fs/f2fs.h +5 -3
@@ -829,13 +829,14 @@ struct f2fs_sb_info {block_t user_block_count;/* # of user blocks */ block_t total_valid_block_count;/* # of valid blocks */ -block_t alloc_valid_block_count;/* # of allocated blocks */ block_t discard_blks;/* discard command candidats */ block_t last_valid_block_count;/* for recovery */ u32 s_next_generation;/* for NFS support */ /* # of pages, see count_type */ struct percpu_counter nr_pages[NR_COUNT_TYPE ]; +/* # of allocated blocks */ +struct percpu_counter alloc_valid_block_count;struct f2fs_mount_info mount_opt;/* mount options */
@@ -1161,8 +1162,9 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi, inode->i_blocks += *count; sbi->total_valid_block_count = sbi->total_valid_block_count + (block_t)(*count); - sbi->alloc_valid_block_count += (block_t)(*count);spin_unlock (&sbi->stat_lock); + +percpu_counter_add (&sbi->alloc_valid_block_count, (*count));return true; }
@@ -1310,11 +1312,11 @@ static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,if (inode) inode->i_blocks++; - sbi->alloc_valid_block_count++; sbi->total_valid_node_count++; sbi->total_valid_block_count++;spin_unlock (&sbi->stat_lock); +percpu_counter_inc (&sbi->alloc_valid_block_count);return true; }
fs/f2fs/recovery.c +3 -2
@@ -49,8 +49,9 @@ static struct kmem_cache *fsync_entry_slab;bool space_for_roll_forward (struct f2fs_sb_info *sbi) { -if (sbi->last_valid_block_count + sbi->alloc_valid_block_count - > sbi->user_block_count) +s64 nalloc =percpu_counter_sum_positive (&sbi->alloc_valid_block_count); + +if (sbi->last_valid_block_count + nalloc > sbi->user_block_count)return false;return true; }
fs/f2fs/super.c +5 -2
@@ -618,6 +618,7 @@ static void destroy_percpu_info(struct f2fs_sb_info *sbi)for (i =0 ; i <NR_COUNT_TYPE ; i++)percpu_counter_destroy (&sbi->nr_pages[i]); +percpu_counter_destroy (&sbi->alloc_valid_block_count); }static void f2fs_put_super (struct super_block *sb)
@@ -1384,7 +1385,9 @@ static int init_percpu_info(struct f2fs_sb_info *sbi)if (err)return err; } -return 0 ; + +return percpu_counter_init (&sbi->alloc_valid_block_count,0 , +GFP_KERNEL ); }/*
@@ -1603,7 +1606,7 @@ try_onemore: sbi->total_valid_block_count =le64_to_cpu (sbi->ckpt->valid_block_count); sbi->last_valid_block_count = sbi->total_valid_block_count; - sbi->alloc_valid_block_count =0 ; +for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);
Signature · 1 line
2.6.3
Jaegeuk Kim
maintainerPATCH 5/5 f2fs: use percpu_counter for total_valid_inode_count
In reply to Jaegeuk KimThis patch uses percpu_counter to avoid stat_lock.
Signed-off-by Jaegeuk Kim <[email protected]>
--- fs/f2fs/f2fs.h | 18 +++++++----------- fs/f2fs/super.c | 11 ++++++++--- 2 files changed, 15 insertions(+), 14 deletions(-)
fs/f2fs/f2fs.h +7 -11
@@ -822,7 +822,6 @@ struct f2fs_sb_info {unsigned int total_sections;/* total section count */ unsigned int total_node_count;/* total node block count */ unsigned int total_valid_node_count;/* valid node block count */ -unsigned int total_valid_inode_count;/* valid inode count */ loff_t max_file_blocks;/* max block index of file */ int active_logs;/* # of active logs */ int dir_level;/* directory level */
@@ -838,6 +837,9 @@ struct f2fs_sb_info {/* # of allocated blocks */ struct percpu_counter alloc_valid_block_count; +/* valid inode count */ +struct percpu_counter total_valid_inode_count; +struct f2fs_mount_info mount_opt;/* mount options */ /* for cleaning operations */
@@ -1343,23 +1345,17 @@ static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)static inline void inc_valid_inode_count (struct f2fs_sb_info *sbi) { -spin_lock (&sbi->stat_lock); -f2fs_bug_on (sbi, sbi->total_valid_inode_count == sbi->total_node_count); - sbi->total_valid_inode_count++; -spin_unlock (&sbi->stat_lock); +percpu_counter_inc (&sbi->total_valid_inode_count); }static inline void dec_valid_inode_count (struct f2fs_sb_info *sbi) { -spin_lock (&sbi->stat_lock); -f2fs_bug_on (sbi, !sbi->total_valid_inode_count); - sbi->total_valid_inode_count--; -spin_unlock (&sbi->stat_lock); +percpu_counter_dec (&sbi->total_valid_inode_count); } -static inline unsigned int valid_inode_count (struct f2fs_sb_info *sbi) +static inline s64 valid_inode_count (struct f2fs_sb_info *sbi) { -return sbi->total_valid_inode_count; +return percpu_counter_sum_positive (&sbi->total_valid_inode_count); } static inline struct page *f2fs_grab_cache_page(struct address_space *mapping,
fs/f2fs/super.c +8 -3
@@ -619,6 +619,7 @@ static void destroy_percpu_info(struct f2fs_sb_info *sbi)for (i =0 ; i <NR_COUNT_TYPE ; i++)percpu_counter_destroy (&sbi->nr_pages[i]);percpu_counter_destroy (&sbi->alloc_valid_block_count); +percpu_counter_destroy (&sbi->total_valid_inode_count); }static void f2fs_put_super (struct super_block *sb)
@@ -1386,7 +1387,11 @@ static int init_percpu_info(struct f2fs_sb_info *sbi)return err; } -return percpu_counter_init (&sbi->alloc_valid_block_count,0 , + err =percpu_counter_init (&sbi->alloc_valid_block_count,0 ,GFP_KERNEL ); +if (err) +return err; + +return percpu_counter_init (&sbi->total_valid_inode_count,0 ,GFP_KERNEL ); }
@@ -1600,8 +1605,8 @@ try_onemore: sbi->total_valid_node_count =le32_to_cpu (sbi->ckpt->valid_node_count); - sbi->total_valid_inode_count = -le32_to_cpu (sbi->ckpt->valid_inode_count); +percpu_counter_set (&sbi->total_valid_inode_count, +le32_to_cpu (sbi->ckpt->valid_inode_count)); sbi->user_block_count =le64_to_cpu (sbi->ckpt->user_block_count); sbi->total_valid_block_count =le64_to_cpu (sbi->ckpt->valid_block_count);
Signature · 1 line
2.6.3