mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 <jaegeuk@kernel.org>
This commit is contained in:
		
							parent
							
								
									f573018491
								
							
						
					
					
						commit
						523be8a6b3
					
				
					 4 changed files with 52 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -299,15 +300,15 @@ static int stat_show(struct seq_file *s, void *v)
 | 
			
		|||
		seq_printf(s, "  - Inner Struct Count: tree: %d(%d), node: %d\n",
 | 
			
		||||
				si->ext_tree, si->zombie_tree, si->ext_node);
 | 
			
		||||
		seq_puts(s, "\nBalancing F2FS Async:\n");
 | 
			
		||||
		seq_printf(s, "  - inmem: %4d, wb_bios: %4d\n",
 | 
			
		||||
		seq_printf(s, "  - inmem: %4lld, wb_bios: %4d\n",
 | 
			
		||||
			   si->inmem_pages, si->wb_bios);
 | 
			
		||||
		seq_printf(s, "  - nodes: %4d in %4d\n",
 | 
			
		||||
		seq_printf(s, "  - nodes: %4lld in %4d\n",
 | 
			
		||||
			   si->ndirty_node, si->node_pages);
 | 
			
		||||
		seq_printf(s, "  - dents: %4d in dirs:%4d\n",
 | 
			
		||||
		seq_printf(s, "  - dents: %4lld in dirs:%4d\n",
 | 
			
		||||
			   si->ndirty_dent, si->ndirty_dirs);
 | 
			
		||||
		seq_printf(s, "  - datas: %4d in files:%4d\n",
 | 
			
		||||
		seq_printf(s, "  - datas: %4lld in files:%4d\n",
 | 
			
		||||
			   si->ndirty_data, si->ndirty_files);
 | 
			
		||||
		seq_printf(s, "  - meta: %4d in %4d\n",
 | 
			
		||||
		seq_printf(s, "  - meta: %4lld in %4d\n",
 | 
			
		||||
			   si->ndirty_meta, si->meta_pages);
 | 
			
		||||
		seq_printf(s, "  - NATs: %9d/%9d\n  - SITs: %9d/%9d\n",
 | 
			
		||||
			   si->dirty_nats, si->nats, si->dirty_sits, si->sits);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -813,7 +813,9 @@ struct f2fs_sb_info {
 | 
			
		|||
	block_t last_valid_block_count;		/* for recovery */
 | 
			
		||||
	u32 s_next_generation;			/* for NFS support */
 | 
			
		||||
	atomic_t nr_wb_bios;			/* # of writeback bios */
 | 
			
		||||
	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 */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1158,7 +1160,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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1171,7 +1173,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)
 | 
			
		||||
| 
						 | 
				
			
			@ -1185,9 +1187,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)
 | 
			
		||||
| 
						 | 
				
			
			@ -1198,8 +1200,10 @@ static inline int get_dirty_pages(struct inode *inode)
 | 
			
		|||
static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int pages_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
 | 
			
		||||
	return ((get_pages(sbi, block_type) + pages_per_sec - 1)
 | 
			
		||||
			>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
 | 
			
		||||
	unsigned int segs = (get_pages(sbi, block_type) + pages_per_sec - 1) >>
 | 
			
		||||
						sbi->log_blocks_per_seg;
 | 
			
		||||
 | 
			
		||||
	return segs / sbi->segs_per_sec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
 | 
			
		||||
| 
						 | 
				
			
			@ -2013,11 +2017,11 @@ struct f2fs_stat_info {
 | 
			
		|||
	unsigned long long hit_largest, hit_cached, hit_rbtree;
 | 
			
		||||
	unsigned long long hit_total, total_ext;
 | 
			
		||||
	int ext_tree, zombie_tree, ext_node;
 | 
			
		||||
	int ndirty_node, ndirty_meta;
 | 
			
		||||
	int ndirty_dent, ndirty_dirs, ndirty_data, ndirty_files;
 | 
			
		||||
	s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
 | 
			
		||||
	unsigned int ndirty_dirs, ndirty_files;
 | 
			
		||||
	int nats, dirty_nats, sits, dirty_sits, fnids;
 | 
			
		||||
	int total_count, utilization;
 | 
			
		||||
	int bg_gc, inmem_pages, wb_bios;
 | 
			
		||||
	int bg_gc, wb_bios;
 | 
			
		||||
	int inline_xattr, inline_inode, inline_dir, orphans;
 | 
			
		||||
	unsigned int valid_count, valid_node_count, valid_inode_count;
 | 
			
		||||
	unsigned int bimodal, avg_vblocks;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -666,6 +674,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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1324,7 +1334,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -1344,9 +1353,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1362,6 +1368,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
 | 
			
		||||
| 
						 | 
				
			
			@ -1552,6 +1570,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 | 
			
		|||
	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)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1754,6 +1776,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 | 
			
		|||
	make_bad_inode(sbi->meta_inode);
 | 
			
		||||
	iput(sbi->meta_inode);
 | 
			
		||||
free_options:
 | 
			
		||||
	destroy_percpu_info(sbi);
 | 
			
		||||
	kfree(options);
 | 
			
		||||
free_sb_buf:
 | 
			
		||||
	kfree(raw_super);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1275,14 +1275,14 @@ TRACE_EVENT(f2fs_destroy_extent_tree,
 | 
			
		|||
 | 
			
		||||
DECLARE_EVENT_CLASS(f2fs_sync_dirty_inodes,
 | 
			
		||||
 | 
			
		||||
	TP_PROTO(struct super_block *sb, int type, int count),
 | 
			
		||||
	TP_PROTO(struct super_block *sb, int type, s64 count),
 | 
			
		||||
 | 
			
		||||
	TP_ARGS(sb, type, count),
 | 
			
		||||
 | 
			
		||||
	TP_STRUCT__entry(
 | 
			
		||||
		__field(dev_t, dev)
 | 
			
		||||
		__field(int, type)
 | 
			
		||||
		__field(int, count)
 | 
			
		||||
		__field(s64, count)
 | 
			
		||||
	),
 | 
			
		||||
 | 
			
		||||
	TP_fast_assign(
 | 
			
		||||
| 
						 | 
				
			
			@ -1291,7 +1291,7 @@ DECLARE_EVENT_CLASS(f2fs_sync_dirty_inodes,
 | 
			
		|||
		__entry->count	= count;
 | 
			
		||||
	),
 | 
			
		||||
 | 
			
		||||
	TP_printk("dev = (%d,%d), %s, dirty count = %d",
 | 
			
		||||
	TP_printk("dev = (%d,%d), %s, dirty count = %lld",
 | 
			
		||||
		show_dev(__entry),
 | 
			
		||||
		show_file_type(__entry->type),
 | 
			
		||||
		__entry->count)
 | 
			
		||||
| 
						 | 
				
			
			@ -1299,14 +1299,14 @@ DECLARE_EVENT_CLASS(f2fs_sync_dirty_inodes,
 | 
			
		|||
 | 
			
		||||
DEFINE_EVENT(f2fs_sync_dirty_inodes, f2fs_sync_dirty_inodes_enter,
 | 
			
		||||
 | 
			
		||||
	TP_PROTO(struct super_block *sb, int type, int count),
 | 
			
		||||
	TP_PROTO(struct super_block *sb, int type, s64 count),
 | 
			
		||||
 | 
			
		||||
	TP_ARGS(sb, type, count)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
DEFINE_EVENT(f2fs_sync_dirty_inodes, f2fs_sync_dirty_inodes_exit,
 | 
			
		||||
 | 
			
		||||
	TP_PROTO(struct super_block *sb, int type, int count),
 | 
			
		||||
	TP_PROTO(struct super_block *sb, int type, s64 count),
 | 
			
		||||
 | 
			
		||||
	TP_ARGS(sb, type, count)
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue