* [PATCH v2] f2fs: add app/fs io stat
@ 2017-08-02 15:21 Chao Yu
2017-08-10 4:45 ` Jaegeuk Kim
0 siblings, 1 reply; 3+ messages in thread
From: Chao Yu @ 2017-08-02 15:21 UTC (permalink / raw)
To: jaegeuk; +Cc: linux-f2fs-devel, linux-kernel, Chao Yu
From: Chao Yu <yuchao0@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 <yuchao0@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]);
+ seq_printf(seq, "fs gc node: %-16llu\n",
+ sbi->write_iostat[FS_NODE_IO]);
+ 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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] f2fs: add app/fs io stat
2017-08-02 15:21 [PATCH v2] f2fs: add app/fs io stat Chao Yu
@ 2017-08-10 4:45 ` Jaegeuk Kim
2017-08-10 6:12 ` Chao Yu
0 siblings, 1 reply; 3+ messages in thread
From: Jaegeuk Kim @ 2017-08-10 4:45 UTC (permalink / raw)
To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel, Chao Yu
Hi Chao,
I've fixed the below in f2fs.git.
On 08/02, Chao Yu wrote:
> From: Chao Yu <yuchao0@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 <yuchao0@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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] f2fs: add app/fs io stat
2017-08-10 4:45 ` Jaegeuk Kim
@ 2017-08-10 6:12 ` Chao Yu
0 siblings, 0 replies; 3+ messages in thread
From: Chao Yu @ 2017-08-10 6:12 UTC (permalink / raw)
To: Jaegeuk Kim, Chao Yu; +Cc: linux-f2fs-devel, linux-kernel
Hi Jaegeuk,
On 2017/8/10 12:45, Jaegeuk Kim wrote:
> Hi Chao,
>
> I've fixed the below in f2fs.git.
Thank you fox fixing it. :)
Thanks,
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-08-10 6:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-02 15:21 [PATCH v2] f2fs: add app/fs io stat Chao Yu
2017-08-10 4:45 ` Jaegeuk Kim
2017-08-10 6:12 ` Chao Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).