Commit 5f9abab4 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: account read IOs and use IO counts for is_idle

This patch adds issued read IO counts which is under block layer.

Chao modified a bit, since:

Below race can cause reversed reference on F2FS_RD_DATA, there is
the same issue in f2fs_submit_page_bio(), fix them by relocate
__submit_bio() and inc_page_count.

Thread A			Thread B
- f2fs_write_begin
 - f2fs_submit_page_read
 - __submit_bio
				- f2fs_read_end_io
				 - __read_end_io
				 - dec_page_count(, F2FS_RD_DATA)
 - inc_page_count(, F2FS_RD_DATA)
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 78efac53
...@@ -52,6 +52,23 @@ static bool __is_cp_guaranteed(struct page *page) ...@@ -52,6 +52,23 @@ static bool __is_cp_guaranteed(struct page *page)
return false; return false;
} }
static enum count_type __read_io_type(struct page *page)
{
struct address_space *mapping = page->mapping;
if (mapping) {
struct inode *inode = mapping->host;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
if (inode->i_ino == F2FS_META_INO(sbi))
return F2FS_RD_META;
if (inode->i_ino == F2FS_NODE_INO(sbi))
return F2FS_RD_NODE;
}
return F2FS_RD_DATA;
}
/* postprocessing steps for read bios */ /* postprocessing steps for read bios */
enum bio_post_read_step { enum bio_post_read_step {
STEP_INITIAL = 0, STEP_INITIAL = 0,
...@@ -82,6 +99,7 @@ static void __read_end_io(struct bio *bio) ...@@ -82,6 +99,7 @@ static void __read_end_io(struct bio *bio)
} else { } else {
SetPageUptodate(page); SetPageUptodate(page);
} }
dec_page_count(F2FS_P_SB(page), __read_io_type(page));
unlock_page(page); unlock_page(page);
} }
if (bio->bi_private) if (bio->bi_private)
...@@ -466,8 +484,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) ...@@ -466,8 +484,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
bio_set_op_attrs(bio, fio->op, fio->op_flags); bio_set_op_attrs(bio, fio->op, fio->op_flags);
if (!is_read_io(fio->op)) inc_page_count(fio->sbi, is_read_io(fio->op) ?
inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page)); __read_io_type(page): WB_DATA_TYPE(fio->page));
__submit_bio(fio->sbi, bio, fio->type); __submit_bio(fio->sbi, bio, fio->type);
return 0; return 0;
...@@ -598,6 +616,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, ...@@ -598,6 +616,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
return -EFAULT; return -EFAULT;
} }
ClearPageError(page); ClearPageError(page);
inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
__submit_bio(F2FS_I_SB(inode), bio, DATA); __submit_bio(F2FS_I_SB(inode), bio, DATA);
return 0; return 0;
} }
...@@ -1586,6 +1605,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping, ...@@ -1586,6 +1605,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
if (bio_add_page(bio, page, blocksize, 0) < blocksize) if (bio_add_page(bio, page, blocksize, 0) < blocksize)
goto submit_and_realloc; goto submit_and_realloc;
inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
ClearPageError(page); ClearPageError(page);
last_block_in_bio = block_nr; last_block_in_bio = block_nr;
goto next_page; goto next_page;
......
...@@ -55,6 +55,9 @@ static void update_general_status(struct f2fs_sb_info *sbi) ...@@ -55,6 +55,9 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt); si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt);
si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA); si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA);
si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA); si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA);
si->nr_rd_data = get_pages(sbi, F2FS_RD_DATA);
si->nr_rd_node = get_pages(sbi, F2FS_RD_NODE);
si->nr_rd_meta = get_pages(sbi, F2FS_RD_META);
if (SM_I(sbi) && SM_I(sbi)->fcc_info) { if (SM_I(sbi) && SM_I(sbi)->fcc_info) {
si->nr_flushed = si->nr_flushed =
atomic_read(&SM_I(sbi)->fcc_info->issued_flush); atomic_read(&SM_I(sbi)->fcc_info->issued_flush);
...@@ -371,7 +374,9 @@ static int stat_show(struct seq_file *s, void *v) ...@@ -371,7 +374,9 @@ static int stat_show(struct seq_file *s, void *v)
seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n", seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n",
si->ext_tree, si->zombie_tree, si->ext_node); si->ext_tree, si->zombie_tree, si->ext_node);
seq_puts(s, "\nBalancing F2FS Async:\n"); seq_puts(s, "\nBalancing F2FS Async:\n");
seq_printf(s, " - IO (CP: %4d, Data: %4d, Flush: (%4d %4d %4d), " seq_printf(s, " - IO_R (Data: %4d, Node: %4d, Meta: %4d\n",
si->nr_rd_data, si->nr_rd_node, si->nr_rd_meta);
seq_printf(s, " - IO_W (CP: %4d, Data: %4d, Flush: (%4d %4d %4d), "
"Discard: (%4d %4d)) cmd: %4d undiscard:%4u\n", "Discard: (%4d %4d)) cmd: %4d undiscard:%4u\n",
si->nr_wb_cp_data, si->nr_wb_data, si->nr_wb_cp_data, si->nr_wb_data,
si->nr_flushing, si->nr_flushed, si->nr_flushing, si->nr_flushed,
......
...@@ -950,6 +950,9 @@ enum count_type { ...@@ -950,6 +950,9 @@ enum count_type {
F2FS_DIRTY_IMETA, F2FS_DIRTY_IMETA,
F2FS_WB_CP_DATA, F2FS_WB_CP_DATA,
F2FS_WB_DATA, F2FS_WB_DATA,
F2FS_RD_DATA,
F2FS_RD_NODE,
F2FS_RD_META,
NR_COUNT_TYPE, NR_COUNT_TYPE,
}; };
...@@ -1392,11 +1395,6 @@ static inline unsigned int f2fs_time_to_wait(struct f2fs_sb_info *sbi, ...@@ -1392,11 +1395,6 @@ static inline unsigned int f2fs_time_to_wait(struct f2fs_sb_info *sbi,
return wait_ms; return wait_ms;
} }
static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
{
return f2fs_time_over(sbi, type);
}
/* /*
* Inline functions * Inline functions
*/ */
...@@ -1787,7 +1785,9 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type) ...@@ -1787,7 +1785,9 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
atomic_inc(&sbi->nr_pages[count_type]); atomic_inc(&sbi->nr_pages[count_type]);
if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES || if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES ||
count_type == F2FS_WB_CP_DATA || count_type == F2FS_WB_DATA) count_type == F2FS_WB_CP_DATA || count_type == F2FS_WB_DATA ||
count_type == F2FS_RD_DATA || count_type == F2FS_RD_NODE ||
count_type == F2FS_RD_META)
return; return;
set_sbi_flag(sbi, SBI_IS_DIRTY); set_sbi_flag(sbi, SBI_IS_DIRTY);
...@@ -2124,6 +2124,15 @@ static inline struct bio *f2fs_bio_alloc(struct f2fs_sb_info *sbi, ...@@ -2124,6 +2124,15 @@ static inline struct bio *f2fs_bio_alloc(struct f2fs_sb_info *sbi,
return bio_alloc(GFP_KERNEL, npages); return bio_alloc(GFP_KERNEL, npages);
} }
static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
{
if (get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_RD_NODE) ||
get_pages(sbi, F2FS_RD_META) || get_pages(sbi, F2FS_WB_DATA) ||
get_pages(sbi, F2FS_WB_CP_DATA))
return false;
return f2fs_time_over(sbi, type);
}
static inline void f2fs_radix_tree_insert(struct radix_tree_root *root, static inline void f2fs_radix_tree_insert(struct radix_tree_root *root,
unsigned long index, void *item) unsigned long index, void *item)
{ {
...@@ -3114,6 +3123,7 @@ struct f2fs_stat_info { ...@@ -3114,6 +3123,7 @@ struct f2fs_stat_info {
int free_nids, avail_nids, alloc_nids; int free_nids, avail_nids, alloc_nids;
int total_count, utilization; int total_count, utilization;
int bg_gc, nr_wb_cp_data, nr_wb_data; int bg_gc, nr_wb_cp_data, nr_wb_data;
int nr_rd_data, nr_rd_node, nr_rd_meta;
unsigned int io_skip_bggc, other_skip_bggc; unsigned int io_skip_bggc, other_skip_bggc;
int nr_flushing, nr_flushed, flush_list_empty; int nr_flushing, nr_flushed, flush_list_empty;
int nr_discarding, nr_discarded; int nr_discarding, nr_discarded;
......
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