|
@@ -557,6 +557,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 */
|
|
|
|
|
@@ -863,6 +864,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 */
|
|
@@ -877,6 +895,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)
|
|
@@ -1068,6 +1087,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;
|
|
@@ -2291,6 +2315,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
|
|
|
*/
|
|
@@ -2418,7 +2467,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);
|
|
@@ -2461,7 +2510,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);
|
|
@@ -2502,7 +2552,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);
|
|
@@ -2555,6 +2605,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);
|