All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 523be8a6 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: use percpu_counter for page counters

This patch substitutes percpu_counter for atomic_counter when counting
various types of pages.
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent f5730184
......@@ -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 @@ 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)) {
......@@ -1754,6 +1776,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);
......
......@@ -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)
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment