Hi Chao,

I've fixed the below in f2fs.git.

On 08/02, Chao Yu wrote:
> From: Chao Yu <yuch...@huawei.com>
> 
> 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
> 
> Signed-off-by: Chao Yu <yuch...@huawei.com>
> ---
> 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(-)
> 
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 3c84a2520796..da5b49183e09 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -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);
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index aefc2a5745d3..c43262dc36de 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -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);
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 5b77451f21c7..b46599d806fc 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -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);
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 407518f42e45..e2b33b87701f 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -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);
>  
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index f57cadae1a30..620dca443b29 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -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;
> diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
> index f38be791fdf9..e63ab0d1f614 100644
> --- a/fs/f2fs/inline.c
> +++ b/fs/f2fs/inline.c
> @@ -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;
>  
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 5483a735847f..b08f0d9bd86f 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -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;
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 336eb03e7902..3c0724d93433 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -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,
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index fc757c8861b7..4ab6dc31a61b 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -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;
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 4908db5a350e..17257fd5733c 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -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_INJECTION
>       ATTR_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]);
> +
> +     /* 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

> +     seq_printf(seq, "fs gc node:    %-16llu\n",
> +                             sbi->write_iostat[FS_NODE_IO]);

                                                FS_GC_NODE_IO

Thanks,

> +     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);
> -- 
> 2.13.0.90.g1eb437020

Reply via email to