f2fs: add app/fs io stat
Chao Yu
maintainerPATCH v2 1/1 f2fs: add app/fs io stat
From: Chao Yu <[email protected]>
This patch enables inner app/fs io stats and introduces below virtual fs nodes for exposing stats info:
/sys/fs/f2fs/<dev>/iostat_enable /proc/fs/f2fs/<dev>/iostat_info
---
v2:
- reorganize printed info of iostat_info.
- add discard stats.
fs/f2fs/checkpoint.c | 34 +++++++++++++++++++++--------- fs/f2fs/data.c | 35 +++++++++++++++++++++++-------- fs/f2fs/f2fs.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- fs/f2fs/file.c | 7 ++++++- fs/f2fs/gc.c | 3 +++ fs/f2fs/inline.c | 1 + fs/f2fs/node.c | 15 +++++++------ fs/f2fs/segment.c | 21 +++++++++++++++++-- fs/f2fs/super.c | 4 ++++ fs/f2fs/sysfs.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 200 insertions(+), 31 deletions(-)
fs/f2fs/checkpoint.c +24 -10
@@ -230,8 +230,9 @@ void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)ra_meta_pages (sbi, index,BIO_MAX_PAGES ,META_POR , true); } -static int f2fs_write_meta_page (struct page *page, -struct writeback_control *wbc) +static int __f2fs_write_meta_page (struct page *page, +struct writeback_control *wbc, +enum iostat_type io_type) {struct f2fs_sb_info *sbi =F2FS_P_SB (page);
@@ -244,7 +245,7 @@ static int f2fs_write_meta_page(struct page *page,if (unlikely (f2fs_cp_error (sbi))) goto redirty_out; -write_meta_page (sbi, page); +write_meta_page (sbi, page, io_type);dec_page_count (sbi,F2FS_DIRTY_META );if (wbc->for_reclaim)
@@ -263,6 +264,12 @@ static int f2fs_write_meta_page(struct page *page,return AOP_WRITEPAGE_ACTIVATE ; } +static int f2fs_write_meta_page (struct page *page, +struct writeback_control *wbc) +{ +return __f2fs_write_meta_page (page, wbc,FS_META_IO ); +} +static int f2fs_write_meta_pages (struct address_space *mapping,struct writeback_control *wbc) {
@@ -283,7 +290,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,trace_f2fs_writepages (mapping->host, wbc,META ); diff =nr_pages_to_write (sbi,META , wbc); - written =sync_meta_pages (sbi,META , wbc->nr_to_write); + written =sync_meta_pages (sbi,META , wbc->nr_to_write,FS_META_IO );mutex_unlock (&sbi->cp_mutex); wbc->nr_to_write =max ((long )0 , wbc->nr_to_write - written - diff);return 0 ;
@@ -295,7 +302,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping, }long sync_meta_pages (struct f2fs_sb_info *sbi,enum page_type type, -long nr_to_write) +long nr_to_write,enum iostat_type io_type) {struct address_space *mapping =META_MAPPING (sbi);pgoff_t index =0 , end =ULONG_MAX , prev =ULONG_MAX ;
@@ -346,7 +353,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,if (!clear_page_dirty_for_io (page)) goto continue_unlock; -if (mapping->a_ops->writepage (page, &wbc)) { +if (__f2fs_write_meta_page (page, &wbc, io_type)) {unlock_page (page);break ; }
@@ -904,7 +911,14 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)if (inode) {unsigned long cur_ino = inode->i_ino; +if (is_dir) +F2FS_I (inode)->cp_task = current; +filemap_fdatawrite (inode->i_mapping); + +if (is_dir) +F2FS_I (inode)->cp_task =NULL ; +iput (inode);/* We need to give cpu to another writers. */ if (ino == cur_ino) {
@@ -1017,7 +1031,7 @@ static int block_operations(struct f2fs_sb_info *sbi)if (get_pages (sbi,F2FS_DIRTY_NODES )) {up_write (&sbi->node_write); - err =sync_node_pages (sbi, &wbc, false); + err =sync_node_pages (sbi, &wbc, false,FS_CP_NODE_IO );if (err) {up_write (&sbi->node_change);f2fs_unlock_all (sbi);
@@ -1115,7 +1129,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)/* Flush all the NAT/SIT pages */ while (get_pages (sbi,F2FS_DIRTY_META )) { -sync_meta_pages (sbi,META ,LONG_MAX ); +sync_meta_pages (sbi,META ,LONG_MAX ,FS_CP_META_IO );if (unlikely (f2fs_cp_error (sbi)))return -EIO ; }
@@ -1194,7 +1208,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)/* Flush all the NAT BITS pages */ while (get_pages (sbi,F2FS_DIRTY_META )) { -sync_meta_pages (sbi,META ,LONG_MAX ); +sync_meta_pages (sbi,META ,LONG_MAX ,FS_CP_META_IO );if (unlikely (f2fs_cp_error (sbi)))return -EIO ; }
@@ -1249,7 +1263,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)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 ); +sync_meta_pages (sbi,META_FLUSH ,LONG_MAX ,FS_CP_META_IO );/* wait for previous submitted meta pages writeback */ wait_on_all_pages_writeback (sbi);
fs/f2fs/data.c +26 -9
@@ -1475,7 +1475,8 @@ int do_write_data_page(struct f2fs_io_info *fio) }static int __write_data_page (struct page *page,bool *submitted, -struct writeback_control *wbc) +struct writeback_control *wbc, +enum iostat_type io_type) {struct inode *inode = page->mapping->host;struct f2fs_sb_info *sbi =F2FS_I_SB (inode);
@@ -1496,6 +1497,7 @@ static int __write_data_page(struct page *page, bool *submitted, .encrypted_page = NULL, .submitted = false, .need_lock = LOCK_RETRY, + .io_type = io_type, };trace_f2fs_writepage (page,DATA );
@@ -1602,7 +1604,7 @@ static int __write_data_page(struct page *page, bool *submitted,static int f2fs_write_data_page (struct page *page,struct writeback_control *wbc) { -return __write_data_page (page,NULL , wbc); +return __write_data_page (page,NULL , wbc,FS_DATA_IO ); }/*
@@ -1611,7 +1613,8 @@ static int f2fs_write_data_page(struct page *page,* warm/hot data page. */ static int f2fs_write_cache_pages (struct address_space *mapping, -struct writeback_control *wbc) +struct writeback_control *wbc, +enum iostat_type io_type) {int ret =0 ;int done =0 ;
@@ -1701,7 +1704,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,if (!clear_page_dirty_for_io (page)) goto continue_unlock; - ret =__write_data_page (page, &submitted, wbc); + ret =__write_data_page (page, &submitted, wbc, io_type);if (unlikely (ret)) {/* * keep nr_to_write, since vfs uses this to
@@ -1756,8 +1759,9 @@ static int f2fs_write_cache_pages(struct address_space *mapping,return ret; } -static int f2fs_write_data_pages (struct address_space *mapping, -struct writeback_control *wbc) +int __f2fs_write_data_pages (struct address_space *mapping, +struct writeback_control *wbc, +enum iostat_type io_type) {struct inode *inode = mapping->host;struct f2fs_sb_info *sbi =F2FS_I_SB (inode);
@@ -1794,7 +1798,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, goto skip_write;blk_start_plug (&plug); - ret =f2fs_write_cache_pages (mapping, wbc); + ret =f2fs_write_cache_pages (mapping, wbc, io_type);blk_finish_plug (&plug);if (wbc->sync_mode ==WB_SYNC_ALL )
@@ -1813,6 +1817,16 @@ static int f2fs_write_data_pages(struct address_space *mapping,return 0 ; } +static int f2fs_write_data_pages (struct address_space *mapping, +struct writeback_control *wbc) +{ +struct inode *inode = mapping->host; + +return __f2fs_write_data_pages (mapping, wbc, +F2FS_I (inode)->cp_task == current ? +FS_CP_DATA_IO :FS_DATA_IO ); +} +static void f2fs_write_failed (struct address_space *mapping,loff_t to) {struct inode *inode = mapping->host;
@@ -2079,10 +2093,13 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)up_read (&F2FS_I (inode)->dio_rwsem[rw]);if (rw ==WRITE ) { -if (err >0 ) +if (err >0 ) { +f2fs_update_iostat (F2FS_I_SB (inode),APP_DIRECT_IO , + err);set_inode_flag (inode,FI_UPDATE_WRITE ); -else if (err <0 ) + }else if (err <0 ) {f2fs_write_failed (mapping, offset + count); + } }trace_f2fs_direct_IO_exit (inode, offset, count, rw, err);
fs/f2fs/f2fs.h +56 -3
113 lines not on this page · raw message
fs/f2fs/file.c +6 -1
@@ -98,6 +98,8 @@ static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)if (!PageUptodate (page))SetPageUptodate (page); +f2fs_update_iostat (sbi,APP_MAPPED_IO ,F2FS_BLKSIZE ); +trace_f2fs_vm_page_mkwrite (page,DATA ); mapped:/* fill the page */
@@ -1815,7 +1817,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)f2fs_stop_checkpoint (sbi, false);break ;case F2FS_GOING_DOWN_METAFLUSH : -sync_meta_pages (sbi,META ,LONG_MAX ); +sync_meta_pages (sbi,META ,LONG_MAX ,FS_META_IO );f2fs_stop_checkpoint (sbi, false);break ;default :
@@ -2694,6 +2696,9 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ret =__generic_file_write_iter (iocb, from);blk_finish_plug (&plug);clear_inode_flag (inode,FI_NO_PREALLOC ); + +if (ret >0 ) +f2fs_update_iostat (F2FS_I_SB (inode),APP_WRITE_IO , ret); }inode_unlock (inode);
fs/f2fs/gc.c +3 -0
@@ -689,6 +689,8 @@ static void move_encrypted_block(struct inode *inode, block_t bidx, fio.new_blkaddr = newaddr;f2fs_submit_page_write (&fio); +f2fs_update_iostat (fio.sbi,FS_GC_DATA_IO ,F2FS_BLKSIZE ); +f2fs_update_data_blkaddr (&dn, newaddr);set_inode_flag (inode,FI_APPEND_WRITE );if (page->index ==0 )
@@ -736,6 +738,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type, .page = page, .encrypted_page = NULL, .need_lock = LOCK_REQ, + .io_type = FS_GC_DATA_IO, };bool is_dirty =PageDirty (page);int err;
fs/f2fs/inline.c +1 -0
@@ -117,6 +117,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) .op_flags = REQ_SYNC | REQ_PRIO, .page = page, .encrypted_page = NULL, + .io_type = FS_DATA_IO, };int dirty, err;
fs/f2fs/node.c +9 -6
@@ -1327,7 +1327,8 @@ static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) }static int __write_node_page (struct page *page,bool atomic,bool *submitted, -struct writeback_control *wbc,bool do_balance) +struct writeback_control *wbc,bool do_balance, +enum iostat_type io_type) {struct f2fs_sb_info *sbi =F2FS_P_SB (page);nid_t nid;
@@ -1340,6 +1341,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, .page = page, .encrypted_page = NULL, .submitted = false, + .io_type = io_type, };trace_f2fs_writepage (page,NODE );
@@ -1408,7 +1410,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,static int f2fs_write_node_page (struct page *page,struct writeback_control *wbc) { -return __write_node_page (page, false,NULL , wbc, false); +return __write_node_page (page, false,NULL , wbc, false,FS_NODE_IO ); } int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
@@ -1496,7 +1498,8 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, ret =__write_node_page (page, atomic && page == last_page, - &submitted, wbc, true); + &submitted, wbc, true, +FS_NODE_IO );if (ret) {unlock_page (page);f2fs_put_page (last_page,0 );
@@ -1534,7 +1537,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, }int sync_node_pages (struct f2fs_sb_info *sbi,struct writeback_control *wbc, -bool do_balance) +bool do_balance,enum iostat_type io_type) {pgoff_t index, end;struct pagevec pvec;
@@ -1613,7 +1616,7 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc,set_dentry_mark (page,0 ); ret =__write_node_page (page, false, &submitted, - wbc, do_balance); + wbc, do_balance, io_type);if (ret)unlock_page (page);else if (submitted)
@@ -1702,7 +1705,7 @@ static int f2fs_write_node_pages(struct address_space *mapping, diff =nr_pages_to_write (sbi,NODE , wbc); wbc->sync_mode =WB_SYNC_NONE ;blk_start_plug (&plug); -sync_node_pages (sbi, wbc, true); +sync_node_pages (sbi, wbc, true,FS_NODE_IO );blk_finish_plug (&plug); wbc->nr_to_write =max ((long )0 , wbc->nr_to_write - diff);return 0 ;
fs/f2fs/segment.c +19 -2
@@ -292,6 +292,7 @@ static int __commit_inmem_pages(struct inode *inode, .type = DATA, .op = REQ_OP_WRITE, .op_flags = REQ_SYNC | REQ_PRIO, + .io_type = FS_DATA_IO, };pgoff_t last_idx =ULONG_MAX ;int err =0 ;
@@ -823,6 +824,8 @@ static void __submit_discard_cmd(struct f2fs_sb_info *sbi,submit_bio (bio);list_move_tail (&dc->list, &dcc->wait_list);__check_sit_bitmap (sbi, dc->start, dc->start + dc->len); + +f2fs_update_iostat (sbi,FS_DISCARD ,1 ); } }else {__remove_discard_cmd (sbi, dc);
@@ -2274,7 +2277,8 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) } } -void write_meta_page (struct f2fs_sb_info *sbi,struct page *page) +void write_meta_page (struct f2fs_sb_info *sbi,struct page *page, +enum iostat_type io_type) {struct f2fs_io_info fio = { .sbi = sbi,
@@ -2293,6 +2297,8 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)set_page_writeback (page);f2fs_submit_page_write (&fio); + +f2fs_update_iostat (sbi, io_type,F2FS_BLKSIZE ); }void write_node_page (unsigned int nid,struct f2fs_io_info *fio)
@@ -2301,6 +2307,8 @@ void write_node_page(unsigned int nid, struct f2fs_io_info *fio)set_summary (&sum, nid,0 ,0 );do_write_page (&sum, fio); + +f2fs_update_iostat (fio->sbi, fio->io_type,F2FS_BLKSIZE ); }void write_data_page (struct dnode_of_data *dn,struct f2fs_io_info *fio)
@@ -2314,13 +2322,22 @@ void write_data_page(struct dnode_of_data *dn, struct f2fs_io_info *fio)set_summary (&sum, dn->nid, dn->ofs_in_node, ni.version);do_write_page (&sum, fio);f2fs_update_data_blkaddr (dn, fio->new_blkaddr); + +f2fs_update_iostat (sbi, fio->io_type,F2FS_BLKSIZE ); }int rewrite_data_page (struct f2fs_io_info *fio) { +int err; + fio->new_blkaddr = fio->old_blkaddr;stat_inc_inplace_blocks (fio->sbi); -return f2fs_submit_page_bio (fio); + + err =f2fs_submit_page_bio (fio); + +f2fs_update_iostat (fio->sbi, fio->io_type,F2FS_BLKSIZE ); + +return err; } void __f2fs_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
fs/f2fs/super.c +4 -0
@@ -2056,6 +2056,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)set_sbi_flag (sbi,SBI_POR_DOING );spin_lock_init (&sbi->stat_lock); +/* init iostat info */ +spin_lock_init (&sbi->iostat_lock); + sbi->iostat_enable = false; +for (i =0 ; i <NR_PAGE_TYPE ; i++) {int n = (i ==META ) ?1 :NR_TEMP_TYPE ;int j;
fs/f2fs/sysfs.c +52 -0
94 lines not on this page · raw message
Signature · 1 line
2.13.0.90.g1eb437020
Jaegeuk Kim
maintainerHi Chao,
I've fixed the below in f2fs.git.
Quoted 644 lines · Chao Yu
From: Chao Yu <[email protected]>
This patch enables inner app/fs io stats and introduces below virtual fs nodes for exposing stats info:
/sys/fs/f2fs/<dev>/iostat_enable /proc/fs/f2fs/<dev>/iostat_infoSigned-off-by Chao Yu <[email protected]>---
v2:
- reorganize printed info ofiostat_info.
- add discard stats.fs/f2fs/checkpoint.c | 34 +++++++++++++++++++++--------- fs/f2fs/data.c | 35 +++++++++++++++++++++++-------- fs/f2fs/f2fs.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- fs/f2fs/file.c | 7 ++++++- fs/f2fs/gc.c | 3 +++ fs/f2fs/inline.c | 1 + fs/f2fs/node.c | 15 +++++++------ fs/f2fs/segment.c | 21 +++++++++++++++++-- fs/f2fs/super.c | 4 ++++ fs/f2fs/sysfs.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 200 insertions(+), 31 deletions(-)fs/f2fs/checkpoint.c +24
-10@@ -230,8 +230,9 @@ void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)ra_meta_pages (sbi, index,BIO_MAX_PAGES ,META_POR , true); } -static int f2fs_write_meta_page (struct page *page, -struct writeback_control *wbc) +static int __f2fs_write_meta_page (struct page *page, +struct writeback_control *wbc, +enum iostat_type io_type) {struct f2fs_sb_info *sbi =F2FS_P_SB (page);@@ -244,7 +245,7 @@ static int f2fs_write_meta_page(struct page *page,if (unlikely (f2fs_cp_error (sbi))) goto redirty_out; -write_meta_page (sbi, page); +write_meta_page (sbi, page, io_type);dec_page_count (sbi,F2FS_DIRTY_META );if (wbc->for_reclaim)@@ -263,6 +264,12 @@ static int f2fs_write_meta_page(struct page *page,return AOP_WRITEPAGE_ACTIVATE ; } +static int f2fs_write_meta_page (struct page *page, +struct writeback_control *wbc) +{ +return __f2fs_write_meta_page (page, wbc,FS_META_IO ); +} +static int f2fs_write_meta_pages (struct address_space *mapping,struct writeback_control *wbc) {@@ -283,7 +290,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,trace_f2fs_writepages (mapping->host, wbc,META ); diff =nr_pages_to_write (sbi,META , wbc); - written =sync_meta_pages (sbi,META , wbc->nr_to_write); + written =sync_meta_pages (sbi,META , wbc->nr_to_write,FS_META_IO );mutex_unlock (&sbi->cp_mutex); wbc->nr_to_write =max ((long )0 , wbc->nr_to_write - written - diff);return 0 ;@@ -295,7 +302,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping, }long sync_meta_pages (struct f2fs_sb_info *sbi,enum page_type type, -long nr_to_write) +long nr_to_write,enum iostat_type io_type) {struct address_space *mapping =META_MAPPING (sbi);pgoff_t index =0 , end =ULONG_MAX , prev =ULONG_MAX ;@@ -346,7 +353,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,if (!clear_page_dirty_for_io (page)) goto continue_unlock; -if (mapping->a_ops->writepage (page, &wbc)) { +if (__f2fs_write_meta_page (page, &wbc, io_type)) {unlock_page (page);break ; }@@ -904,7 +911,14 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)if (inode) {unsigned long cur_ino = inode->i_ino; +if (is_dir) +F2FS_I (inode)->cp_task = current; +filemap_fdatawrite (inode->i_mapping); + +if (is_dir) +F2FS_I (inode)->cp_task =NULL ; +iput (inode);/* We need to give cpu to another writers. */ if (ino == cur_ino) {@@ -1017,7 +1031,7 @@ static int block_operations(struct f2fs_sb_info *sbi)if (get_pages (sbi,F2FS_DIRTY_NODES )) {up_write (&sbi->node_write); - err =sync_node_pages (sbi, &wbc, false); + err =sync_node_pages (sbi, &wbc, false,FS_CP_NODE_IO );if (err) {up_write (&sbi->node_change);f2fs_unlock_all (sbi);@@ -1115,7 +1129,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)/* Flush all the NAT/SIT pages */ while (get_pages (sbi,F2FS_DIRTY_META )) { -sync_meta_pages (sbi,META ,LONG_MAX ); +sync_meta_pages (sbi,META ,LONG_MAX ,FS_CP_META_IO );if (unlikely (f2fs_cp_error (sbi)))return -EIO ; }@@ -1194,7 +1208,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)/* Flush all the NAT BITS pages */ while (get_pages (sbi,F2FS_DIRTY_META )) { -sync_meta_pages (sbi,META ,LONG_MAX ); +sync_meta_pages (sbi,META ,LONG_MAX ,FS_CP_META_IO );if (unlikely (f2fs_cp_error (sbi)))return -EIO ; }@@ -1249,7 +1263,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)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 ); +sync_meta_pages (sbi,META_FLUSH ,LONG_MAX ,FS_CP_META_IO );/* wait for previous submitted meta pages writeback */ wait_on_all_pages_writeback (sbi);fs/f2fs/data.c +26
-9@@ -1475,7 +1475,8 @@ int do_write_data_page(struct f2fs_io_info *fio) }static int __write_data_page (struct page *page,bool *submitted, -struct writeback_control *wbc) +struct writeback_control *wbc, +enum iostat_type io_type) {struct inode *inode = page->mapping->host;struct f2fs_sb_info *sbi =F2FS_I_SB (inode);@@ -1496,6 +1497,7 @@ static int __write_data_page(struct page *page, bool *submitted, .encrypted_page = NULL, .submitted = false, .need_lock = LOCK_RETRY, + .io_type = io_type, };trace_f2fs_writepage (page,DATA );@@ -1602,7 +1604,7 @@ static int __write_data_page(struct page *page, bool *submitted,static int f2fs_write_data_page (struct page *page,struct writeback_control *wbc) { -return __write_data_page (page,NULL , wbc); +return __write_data_page (page,NULL , wbc,FS_DATA_IO ); }/* @@ -1611,7 +1613,8 @@ static int f2fs_write_data_page(struct page *page,* warm/hot data page. */ static int f2fs_write_cache_pages (struct address_space *mapping, -struct writeback_control *wbc) +struct writeback_control *wbc, +enum iostat_type io_type) {int ret =0 ;int done =0 ;@@ -1701,7 +1704,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,if (!clear_page_dirty_for_io (page)) goto continue_unlock; - ret =__write_data_page (page, &submitted, wbc); + ret =__write_data_page (page, &submitted, wbc, io_type);if (unlikely (ret)) {/* * keep nr_to_write, since vfs uses this to @@ -1756,8 +1759,9 @@ static int f2fs_write_cache_pages(struct address_space *mapping,return ret; } -static int f2fs_write_data_pages (struct address_space *mapping, -struct writeback_control *wbc) +int __f2fs_write_data_pages (struct address_space *mapping, +struct writeback_control *wbc, +enum iostat_type io_type) {struct inode *inode = mapping->host;struct f2fs_sb_info *sbi =F2FS_I_SB (inode);@@ -1794,7 +1798,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, goto skip_write;blk_start_plug (&plug); - ret =f2fs_write_cache_pages (mapping, wbc); + ret =f2fs_write_cache_pages (mapping, wbc, io_type);blk_finish_plug (&plug);if (wbc->sync_mode ==WB_SYNC_ALL )@@ -1813,6 +1817,16 @@ static int f2fs_write_data_pages(struct address_space *mapping,return 0 ; } +static int f2fs_write_data_pages (struct address_space *mapping, +struct writeback_control *wbc) +{ +struct inode *inode = mapping->host; + +return __f2fs_write_data_pages (mapping, wbc, +F2FS_I (inode)->cp_task == current ? +FS_CP_DATA_IO :FS_DATA_IO ); +} +static void f2fs_write_failed (struct address_space *mapping,loff_t to) {struct inode *inode = mapping->host;@@ -2079,10 +2093,13 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)up_read (&F2FS_I (inode)->dio_rwsem[rw]);if (rw ==WRITE ) { -if (err >0 ) +if (err >0 ) { +f2fs_update_iostat (F2FS_I_SB (inode),APP_DIRECT_IO , + err);set_inode_flag (inode,FI_UPDATE_WRITE ); -else if (err <0 ) + }else if (err <0 ) {f2fs_write_failed (mapping, offset + count); + } }trace_f2fs_direct_IO_exit (inode, offset, count, rw, err);fs/f2fs/f2fs.h +56
-3@@ -561,6 +561,7 @@ struct f2fs_inode_info {f2fs_hash_t chash;/* hash value of given file name */ unsigned int clevel;/* maximum level of given file name */ struct task_struct *task;/* lookup and create consistency */ +struct task_struct *cp_task;/* separate cp/wb IO stats*/ nid_t i_xattr_nid;/* node id that contains xattrs */ loff_t last_disk_size;/* lastly written file size */ @@ -867,6 +868,23 @@ enum need_lock_type { LOCK_RETRY, }; +enum iostat_type { +APP_DIRECT_IO ,/* app direct IOs */ +APP_BUFFERED_IO ,/* app buffered IOs */ +APP_WRITE_IO ,/* app write IOs */ +APP_MAPPED_IO ,/* app mapped IOs */ +FS_DATA_IO ,/* data IOs from kworker/fsync/reclaimer */ +FS_NODE_IO ,/* node IOs from kworker/fsync/reclaimer */ +FS_META_IO ,/* meta IOs from kworker/reclaimer */ +FS_GC_DATA_IO ,/* data IOs from forground gc */ +FS_GC_NODE_IO ,/* node IOs from forground gc */ +FS_CP_DATA_IO ,/* data IOs from checkpoint */ +FS_CP_NODE_IO ,/* node IOs from checkpoint */ +FS_CP_META_IO ,/* meta IOs from checkpoint */ +FS_DISCARD ,/* discard */ +NR_IO_TYPE , +}; +struct f2fs_io_info {struct f2fs_sb_info *sbi;/* f2fs_sb_info pointer */ enum page_type type;/* contains DATA/NODE/META/META_FLUSH */ @@ -881,6 +899,7 @@ struct f2fs_io_info {bool submitted;/* indicate IO submission */ int need_lock;/* indicate we need to lock cp_rwsem */ bool in_list;/* indicate fio is in io_list */ +enum iostat_type io_type;/* io type */ };#define is_read_io (rw) ((rw) == READ)@@ -1072,6 +1091,11 @@ struct f2fs_sb_info {#endif spinlock_t stat_lock;/* lock for stat operations */ +/* For app/fs IO statistics */ +spinlock_t iostat_lock; +unsigned long long write_iostat[NR_IO_TYPE ]; +bool iostat_enable; +/* For sysfs suppport */ struct kobject s_kobj;struct completion s_kobj_unregister;@@ -2295,6 +2319,31 @@ static inline int get_extra_isize(struct inode *inode) sizeof((f2fs_inode)->field)) \ <= (F2FS_OLD_ATTRIBUTE_SIZE + extra_isize)) \ +static inline void f2fs_reset_iostat (struct f2fs_sb_info *sbi) +{ +int i; + +spin_lock (&sbi->iostat_lock); +for (i =0 ; i <NR_IO_TYPE ; i++) + sbi->write_iostat[i] =0 ; +spin_unlock (&sbi->iostat_lock); +} + +static inline void f2fs_update_iostat (struct f2fs_sb_info *sbi, +enum iostat_type type,unsigned long long io_bytes) +{ +if (!sbi->iostat_enable) +return ; +spin_lock (&sbi->iostat_lock); + sbi->write_iostat[type] += io_bytes; + +if (type ==APP_WRITE_IO || type ==APP_DIRECT_IO ) + sbi->write_iostat[APP_BUFFERED_IO ] = + sbi->write_iostat[APP_WRITE_IO ] - + sbi->write_iostat[APP_DIRECT_IO ]; +spin_unlock (&sbi->iostat_lock); +} +/* * file.c */ @@ -2421,7 +2470,7 @@ void move_node_page(struct page *node_page, int gc_type);int fsync_node_pages (struct f2fs_sb_info *sbi,struct inode *inode,struct writeback_control *wbc,bool atomic);int sync_node_pages (struct f2fs_sb_info *sbi,struct writeback_control *wbc, -bool do_balance); +bool do_balance,enum iostat_type io_type);void build_free_nids (struct f2fs_sb_info *sbi,bool sync,bool mount);bool alloc_nid (struct f2fs_sb_info *sbi,nid_t *nid);void alloc_nid_done (struct f2fs_sb_info *sbi,nid_t nid);@@ -2464,7 +2513,8 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);bool exist_trim_candidates (struct f2fs_sb_info *sbi,struct cp_control *cpc);struct page *get_sum_page (struct f2fs_sb_info *sbi,unsigned int segno);void update_meta_page (struct f2fs_sb_info *sbi,void *src,block_t blk_addr); -void write_meta_page (struct f2fs_sb_info *sbi,struct page *page); +void write_meta_page (struct f2fs_sb_info *sbi,struct page *page, +enum iostat_type io_type);void write_node_page (unsigned int nid,struct f2fs_io_info *fio);void write_data_page (struct dnode_of_data *dn,struct f2fs_io_info *fio);int rewrite_data_page (struct f2fs_io_info *fio);@@ -2505,7 +2555,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, int type, bool sync);void ra_meta_pages_cond (struct f2fs_sb_info *sbi,pgoff_t index);long sync_meta_pages (struct f2fs_sb_info *sbi,enum page_type type, -long nr_to_write); +long nr_to_write,enum iostat_type io_type);void add_ino_entry (struct f2fs_sb_info *sbi,nid_t ino,int type);void remove_ino_entry (struct f2fs_sb_info *sbi,nid_t ino,int type);void release_ino_entry (struct f2fs_sb_info *sbi,bool all);@@ -2558,6 +2608,9 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,int f2fs_fiemap (struct inode *inode,struct fiemap_extent_info *fieinfo,u64 start,u64 len);void f2fs_set_page_dirty_nobuffers (struct page *page); +int __f2fs_write_data_pages (struct address_space *mapping, +struct writeback_control *wbc, +enum iostat_type io_type);void f2fs_invalidate_page (struct page *page,unsigned int offset,unsigned int length);int f2fs_release_page (struct page *page,gfp_t wait);fs/f2fs/file.c +6
-1@@ -98,6 +98,8 @@ static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)if (!PageUptodate (page))SetPageUptodate (page); +f2fs_update_iostat (sbi,APP_MAPPED_IO ,F2FS_BLKSIZE ); +trace_f2fs_vm_page_mkwrite (page,DATA ); mapped:/* fill the page */ @@ -1815,7 +1817,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)f2fs_stop_checkpoint (sbi, false);break ;case F2FS_GOING_DOWN_METAFLUSH : -sync_meta_pages (sbi,META ,LONG_MAX ); +sync_meta_pages (sbi,META ,LONG_MAX ,FS_META_IO );f2fs_stop_checkpoint (sbi, false);break ;default :@@ -2694,6 +2696,9 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ret =__generic_file_write_iter (iocb, from);blk_finish_plug (&plug);clear_inode_flag (inode,FI_NO_PREALLOC ); + +if (ret >0 ) +f2fs_update_iostat (F2FS_I_SB (inode),APP_WRITE_IO , ret); }inode_unlock (inode);fs/f2fs/gc.c +3
-0@@ -689,6 +689,8 @@ static void move_encrypted_block(struct inode *inode, block_t bidx, fio.new_blkaddr = newaddr;f2fs_submit_page_write (&fio); +f2fs_update_iostat (fio.sbi,FS_GC_DATA_IO ,F2FS_BLKSIZE ); +f2fs_update_data_blkaddr (&dn, newaddr);set_inode_flag (inode,FI_APPEND_WRITE );if (page->index ==0 )@@ -736,6 +738,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type, .page = page, .encrypted_page = NULL, .need_lock = LOCK_REQ, + .io_type = FS_GC_DATA_IO, };bool is_dirty =PageDirty (page);int err;fs/f2fs/inline.c +1
-0@@ -117,6 +117,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) .op_flags = REQ_SYNC | REQ_PRIO, .page = page, .encrypted_page = NULL, + .io_type = FS_DATA_IO, };int dirty, err;fs/f2fs/node.c +9
-6@@ -1327,7 +1327,8 @@ static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) }static int __write_node_page (struct page *page,bool atomic,bool *submitted, -struct writeback_control *wbc,bool do_balance) +struct writeback_control *wbc,bool do_balance, +enum iostat_type io_type) {struct f2fs_sb_info *sbi =F2FS_P_SB (page);nid_t nid;@@ -1340,6 +1341,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, .page = page, .encrypted_page = NULL, .submitted = false, + .io_type = io_type, };trace_f2fs_writepage (page,NODE );@@ -1408,7 +1410,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,static int f2fs_write_node_page (struct page *page,struct writeback_control *wbc) { -return __write_node_page (page, false,NULL , wbc, false); +return __write_node_page (page, false,NULL , wbc, false,FS_NODE_IO ); } int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,@@ -1496,7 +1498,8 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, ret =__write_node_page (page, atomic && page == last_page, - &submitted, wbc, true); + &submitted, wbc, true, +FS_NODE_IO );if (ret) {unlock_page (page);f2fs_put_page (last_page,0 );@@ -1534,7 +1537,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, }int sync_node_pages (struct f2fs_sb_info *sbi,struct writeback_control *wbc, -bool do_balance) +bool do_balance,enum iostat_type io_type) {pgoff_t index, end;struct pagevec pvec;@@ -1613,7 +1616,7 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc,set_dentry_mark (page,0 ); ret =__write_node_page (page, false, &submitted, - wbc, do_balance); + wbc, do_balance, io_type);if (ret)unlock_page (page);else if (submitted)@@ -1702,7 +1705,7 @@ static int f2fs_write_node_pages(struct address_space *mapping, diff =nr_pages_to_write (sbi,NODE , wbc); wbc->sync_mode =WB_SYNC_NONE ;blk_start_plug (&plug); -sync_node_pages (sbi, wbc, true); +sync_node_pages (sbi, wbc, true,FS_NODE_IO );blk_finish_plug (&plug); wbc->nr_to_write =max ((long )0 , wbc->nr_to_write - diff);return 0 ;fs/f2fs/segment.c +19
-2@@ -292,6 +292,7 @@ static int __commit_inmem_pages(struct inode *inode, .type = DATA, .op = REQ_OP_WRITE, .op_flags = REQ_SYNC | REQ_PRIO, + .io_type = FS_DATA_IO, };pgoff_t last_idx =ULONG_MAX ;int err =0 ;@@ -823,6 +824,8 @@ static void __submit_discard_cmd(struct f2fs_sb_info *sbi,submit_bio (bio);list_move_tail (&dc->list, &dcc->wait_list);__check_sit_bitmap (sbi, dc->start, dc->start + dc->len); + +f2fs_update_iostat (sbi,FS_DISCARD ,1 ); } }else {__remove_discard_cmd (sbi, dc);@@ -2274,7 +2277,8 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) } } -void write_meta_page (struct f2fs_sb_info *sbi,struct page *page) +void write_meta_page (struct f2fs_sb_info *sbi,struct page *page, +enum iostat_type io_type) {struct f2fs_io_info fio = { .sbi = sbi,@@ -2293,6 +2297,8 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)set_page_writeback (page);f2fs_submit_page_write (&fio); + +f2fs_update_iostat (sbi, io_type,F2FS_BLKSIZE ); }void write_node_page (unsigned int nid,struct f2fs_io_info *fio)@@ -2301,6 +2307,8 @@ void write_node_page(unsigned int nid, struct f2fs_io_info *fio)set_summary (&sum, nid,0 ,0 );do_write_page (&sum, fio); + +f2fs_update_iostat (fio->sbi, fio->io_type,F2FS_BLKSIZE ); }void write_data_page (struct dnode_of_data *dn,struct f2fs_io_info *fio)@@ -2314,13 +2322,22 @@ void write_data_page(struct dnode_of_data *dn, struct f2fs_io_info *fio)set_summary (&sum, dn->nid, dn->ofs_in_node, ni.version);do_write_page (&sum, fio);f2fs_update_data_blkaddr (dn, fio->new_blkaddr); + +f2fs_update_iostat (sbi, fio->io_type,F2FS_BLKSIZE ); }int rewrite_data_page (struct f2fs_io_info *fio) { +int err; + fio->new_blkaddr = fio->old_blkaddr;stat_inc_inplace_blocks (fio->sbi); -return f2fs_submit_page_bio (fio); + + err =f2fs_submit_page_bio (fio); + +f2fs_update_iostat (fio->sbi, fio->io_type,F2FS_BLKSIZE ); + +return err; } void __f2fs_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,fs/f2fs/super.c +4
-0@@ -2056,6 +2056,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)set_sbi_flag (sbi,SBI_POR_DOING );spin_lock_init (&sbi->stat_lock); +/* init iostat info */ +spin_lock_init (&sbi->iostat_lock); + sbi->iostat_enable = false; +for (i =0 ; i <NR_PAGE_TYPE ; i++) {int n = (i ==META ) ?1 :NR_TEMP_TYPE ;int j;fs/f2fs/sysfs.c +24
-0@@ -157,6 +157,10 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,return -EINVAL ; *ui = t; + +if (!strcmp (a->attr.name,"iostat_enable" ) && *ui ==0 ) +f2fs_reset_iostat (sbi); +return count; }@@ -255,6 +259,7 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);F2FS_RW_ATTR (F2FS_SBI , f2fs_sb_info, dir_level, dir_level);F2FS_RW_ATTR (F2FS_SBI , f2fs_sb_info, cp_interval, interval_time[CP_TIME ]);F2FS_RW_ATTR (F2FS_SBI , f2fs_sb_info, idle_interval, interval_time[REQ_TIME ]); +F2FS_RW_ATTR (F2FS_SBI , f2fs_sb_info, iostat_enable, iostat_enable);#ifdef CONFIG_F2FS_FAULT_INJECTION F2FS_RW_ATTR (FAULT_INFO_RATE , f2fs_fault_info, inject_rate, inject_rate);F2FS_RW_ATTR (FAULT_INFO_TYPE , f2fs_fault_info, inject_type, inject_type);@@ -294,6 +299,7 @@ static struct attribute *f2fs_attrs[] = {ATTR_LIST (dirty_nats_ratio),ATTR_LIST (cp_interval),ATTR_LIST (idle_interval), +ATTR_LIST (iostat_enable), #ifdef CONFIG_F2FS_FAULT_INJECTIONATTR_LIST (inject_rate), ATTR_LIST(inject_type),@@ -397,6 +403,48 @@ static int segment_bits_seq_show(struct seq_file *seq, void *offset)return 0 ; } +static int iostat_info_seq_show (struct seq_file *seq,void *offset) +{ +struct super_block *sb = seq->private; +struct f2fs_sb_info *sbi =F2FS_SB (sb); +time64_t now =ktime_get_real_seconds (); + +if (!sbi->iostat_enable) +return 0 ; + +seq_printf (seq,"time: %-16llu\n" , now); + +/* print app IOs */ +seq_printf (seq,"app buffered: %-16llu\n" , + sbi->write_iostat[APP_BUFFERED_IO ]); +seq_printf (seq,"app direct: %-16llu\n" , + sbi->write_iostat[APP_DIRECT_IO ]); +seq_printf (seq,"app mapped: %-16llu\n" , + sbi->write_iostat[APP_MAPPED_IO ]);
fs/f2fs/sysfs.c static int segment_bits_seq_show(struct seq_file *seq, void *offset) · line 433
Quoted 10 lines
fs/f2fs/sysfs.c +10
-0+ +/* print fs IOs */ +seq_printf (seq,"fs data: %-16llu\n" , + sbi->write_iostat[FS_DATA_IO ]); +seq_printf (seq,"fs node: %-16llu\n" , + sbi->write_iostat[FS_NODE_IO ]); +seq_printf (seq,"fs meta: %-16llu\n" , + sbi->write_iostat[FS_META_IO ]); +seq_printf (seq,"fs gc data: %-16llu\n" , + sbi->write_iostat[FS_DATA_IO ]);
FS_GC_DATA_IO
fs/f2fs/sysfs.c static int segment_bits_seq_show(struct seq_file *seq, void *offset) · line 435
Quoted 2 lines
fs/f2fs/sysfs.c +2
-0+seq_printf (seq,"fs gc node: %-16llu\n" , + sbi->write_iostat[FS_NODE_IO ]);
FS_GC_NODE_IO
Thanks,
Quoted 42 lines
fs/f2fs/sysfs.c +16
-0+seq_printf (seq,"fs cp data: %-16llu\n" , + sbi->write_iostat[FS_CP_DATA_IO ]); +seq_printf (seq,"fs cp node: %-16llu\n" , + sbi->write_iostat[FS_CP_NODE_IO ]); +seq_printf (seq,"fs cp meta: %-16llu\n" , + sbi->write_iostat[FS_CP_META_IO ]); +seq_printf (seq,"fs discard: %-16llu\n" , + sbi->write_iostat[FS_DISCARD ]); + +return 0 ; +} +#define F2FS_PROC_FILE_DEF (_name) \ static int _name##_open_fs(struct inode *inode, struct file *file) \ { \@@ -412,6 +460,7 @@ static const struct file_operations f2fs_seq_##_name##_fops = { \F2FS_PROC_FILE_DEF (segment_info);F2FS_PROC_FILE_DEF (segment_bits); +F2FS_PROC_FILE_DEF (iostat_info);int __init f2fs_init_sysfs (void ) {@@ -460,6 +509,8 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi) &f2fs_seq_segment_info_fops, sb);proc_create_data ("segment_bits" ,S_IRUGO , sbi->s_proc, &f2fs_seq_segment_bits_fops, sb); +proc_create_data ("iostat_info" ,S_IRUGO , sbi->s_proc, + &f2fs_seq_iostat_info_fops, sb); }return 0 ; }@@ -467,6 +518,7 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi)void f2fs_unregister_sysfs (struct f2fs_sb_info *sbi) {if (sbi->s_proc) { +remove_proc_entry ("iostat_info" , sbi->s_proc);remove_proc_entry ("segment_info" , sbi->s_proc);remove_proc_entry ("segment_bits" , sbi->s_proc);remove_proc_entry (sbi->sb->s_id, f2fs_proc_root);Signature · 1 line
2.13.0.90.g1eb437020
Hi Jaegeuk,
Quoted 3 lines · Jaegeuk Kim
Hi Chao,
I've fixed the below in f2fs.git.
Thank you fox fixing it. :)
Thanks,