mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	f2fs: support read iostat
Adds to support accounting read IOs from userspace/kernel. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
		
							parent
							
								
									df42339975
								
							
						
					
					
						commit
						8b83ac81f4
					
				
					 8 changed files with 118 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -86,6 +86,8 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
 | 
			
		|||
		return ERR_PTR(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f2fs_update_iostat(sbi, FS_META_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
 | 
			
		||||
	lock_page(page);
 | 
			
		||||
	if (unlikely(page->mapping != mapping)) {
 | 
			
		||||
		f2fs_put_page(page, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -266,6 +268,9 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
 | 
			
		|||
		fio.page = page;
 | 
			
		||||
		err = f2fs_submit_page_bio(&fio);
 | 
			
		||||
		f2fs_put_page(page, err ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
		if (!err)
 | 
			
		||||
			f2fs_update_iostat(sbi, FS_META_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	blk_finish_plug(&plug);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1033,6 +1033,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
 | 
			
		|||
	}
 | 
			
		||||
	ClearPageError(page);
 | 
			
		||||
	inc_page_count(sbi, F2FS_RD_DATA);
 | 
			
		||||
	f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
	__submit_bio(sbi, bio, DATA);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2038,6 +2039,7 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
 | 
			
		|||
		goto submit_and_realloc;
 | 
			
		||||
 | 
			
		||||
	inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
 | 
			
		||||
	f2fs_update_iostat(F2FS_I_SB(inode), FS_DATA_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
	ClearPageError(page);
 | 
			
		||||
	*last_block_in_bio = block_nr;
 | 
			
		||||
	goto out;
 | 
			
		||||
| 
						 | 
				
			
			@ -2173,6 +2175,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
 | 
			
		|||
			goto submit_and_realloc;
 | 
			
		||||
 | 
			
		||||
		inc_page_count(sbi, F2FS_RD_DATA);
 | 
			
		||||
		f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
		ClearPageError(page);
 | 
			
		||||
		*last_block_in_bio = blkaddr;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3526,6 +3529,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 | 
			
		|||
		} else if (err < 0) {
 | 
			
		||||
			f2fs_write_failed(mapping, offset + count);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (err > 0)
 | 
			
		||||
			f2fs_update_iostat(sbi, APP_DIRECT_READ_IO, err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1088,8 +1088,9 @@ enum cp_reason_type {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
enum iostat_type {
 | 
			
		||||
	APP_DIRECT_IO,			/* app direct IOs */
 | 
			
		||||
	APP_BUFFERED_IO,		/* app buffered IOs */
 | 
			
		||||
	/* WRITE IO */
 | 
			
		||||
	APP_DIRECT_IO,			/* app direct write IOs */
 | 
			
		||||
	APP_BUFFERED_IO,		/* app buffered write IOs */
 | 
			
		||||
	APP_WRITE_IO,			/* app write IOs */
 | 
			
		||||
	APP_MAPPED_IO,			/* app mapped IOs */
 | 
			
		||||
	FS_DATA_IO,			/* data IOs from kworker/fsync/reclaimer */
 | 
			
		||||
| 
						 | 
				
			
			@ -1100,6 +1101,17 @@ enum iostat_type {
 | 
			
		|||
	FS_CP_DATA_IO,			/* data IOs from checkpoint */
 | 
			
		||||
	FS_CP_NODE_IO,			/* node IOs from checkpoint */
 | 
			
		||||
	FS_CP_META_IO,			/* meta IOs from checkpoint */
 | 
			
		||||
 | 
			
		||||
	/* READ IO */
 | 
			
		||||
	APP_DIRECT_READ_IO,		/* app direct read IOs */
 | 
			
		||||
	APP_BUFFERED_READ_IO,		/* app buffered read IOs */
 | 
			
		||||
	APP_READ_IO,			/* app read IOs */
 | 
			
		||||
	APP_MAPPED_READ_IO,		/* app mapped read IOs */
 | 
			
		||||
	FS_DATA_READ_IO,		/* data read IOs */
 | 
			
		||||
	FS_NODE_READ_IO,		/* node read IOs */
 | 
			
		||||
	FS_META_READ_IO,		/* meta read IOs */
 | 
			
		||||
 | 
			
		||||
	/* other */
 | 
			
		||||
	FS_DISCARD,			/* discard */
 | 
			
		||||
	NR_IO_TYPE,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1504,8 +1516,8 @@ struct f2fs_sb_info {
 | 
			
		|||
 | 
			
		||||
	/* For app/fs IO statistics */
 | 
			
		||||
	spinlock_t iostat_lock;
 | 
			
		||||
	unsigned long long write_iostat[NR_IO_TYPE];
 | 
			
		||||
	unsigned long long prev_write_iostat[NR_IO_TYPE];
 | 
			
		||||
	unsigned long long rw_iostat[NR_IO_TYPE];
 | 
			
		||||
	unsigned long long prev_rw_iostat[NR_IO_TYPE];
 | 
			
		||||
	bool iostat_enable;
 | 
			
		||||
	unsigned long iostat_next_period;
 | 
			
		||||
	unsigned int iostat_period_ms;
 | 
			
		||||
| 
						 | 
				
			
			@ -3013,8 +3025,8 @@ static inline void f2fs_reset_iostat(struct f2fs_sb_info *sbi)
 | 
			
		|||
 | 
			
		||||
	spin_lock(&sbi->iostat_lock);
 | 
			
		||||
	for (i = 0; i < NR_IO_TYPE; i++) {
 | 
			
		||||
		sbi->write_iostat[i] = 0;
 | 
			
		||||
		sbi->prev_write_iostat[i] = 0;
 | 
			
		||||
		sbi->rw_iostat[i] = 0;
 | 
			
		||||
		sbi->prev_rw_iostat[i] = 0;
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock(&sbi->iostat_lock);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3027,12 +3039,17 @@ static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
 | 
			
		|||
	if (!sbi->iostat_enable)
 | 
			
		||||
		return;
 | 
			
		||||
	spin_lock(&sbi->iostat_lock);
 | 
			
		||||
	sbi->write_iostat[type] += io_bytes;
 | 
			
		||||
	sbi->rw_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];
 | 
			
		||||
		sbi->rw_iostat[APP_BUFFERED_IO] =
 | 
			
		||||
			sbi->rw_iostat[APP_WRITE_IO] -
 | 
			
		||||
			sbi->rw_iostat[APP_DIRECT_IO];
 | 
			
		||||
 | 
			
		||||
	if (type == APP_READ_IO || type == APP_DIRECT_READ_IO)
 | 
			
		||||
		sbi->rw_iostat[APP_BUFFERED_READ_IO] =
 | 
			
		||||
			sbi->rw_iostat[APP_READ_IO] -
 | 
			
		||||
			sbi->rw_iostat[APP_DIRECT_READ_IO];
 | 
			
		||||
	spin_unlock(&sbi->iostat_lock);
 | 
			
		||||
 | 
			
		||||
	f2fs_record_iostat(sbi);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,10 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
 | 
			
		|||
	ret = filemap_fault(vmf);
 | 
			
		||||
	up_read(&F2FS_I(inode)->i_mmap_sem);
 | 
			
		||||
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		f2fs_update_iostat(F2FS_I_SB(inode), APP_MAPPED_READ_IO,
 | 
			
		||||
							F2FS_BLKSIZE);
 | 
			
		||||
 | 
			
		||||
	trace_f2fs_filemap_fault(inode, vmf->pgoff, (unsigned long)ret);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -3510,11 +3514,17 @@ static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 | 
			
		|||
{
 | 
			
		||||
	struct file *file = iocb->ki_filp;
 | 
			
		||||
	struct inode *inode = file_inode(file);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!f2fs_is_compress_backend_ready(inode))
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	return generic_file_read_iter(iocb, iter);
 | 
			
		||||
	ret = generic_file_read_iter(iocb, iter);
 | 
			
		||||
 | 
			
		||||
	if (ret > 0)
 | 
			
		||||
		f2fs_update_iostat(F2FS_I_SB(inode), APP_READ_IO, ret);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -737,6 +737,9 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
 | 
			
		|||
		goto put_encrypted_page;
 | 
			
		||||
	f2fs_put_page(fio.encrypted_page, 0);
 | 
			
		||||
	f2fs_put_page(page, 1);
 | 
			
		||||
 | 
			
		||||
	f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
put_encrypted_page:
 | 
			
		||||
	f2fs_put_page(fio.encrypted_page, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -840,6 +843,9 @@ static int move_data_block(struct inode *inode, block_t bidx,
 | 
			
		|||
			f2fs_put_page(mpage, 1);
 | 
			
		||||
			goto up_out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		f2fs_update_iostat(fio.sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
 | 
			
		||||
		lock_page(mpage);
 | 
			
		||||
		if (unlikely(mpage->mapping != META_MAPPING(fio.sbi) ||
 | 
			
		||||
						!PageUptodate(mpage))) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1300,7 +1300,13 @@ static int read_node_page(struct page *page, int op_flags)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr;
 | 
			
		||||
	return f2fs_submit_page_bio(&fio);
 | 
			
		||||
 | 
			
		||||
	err = f2fs_submit_page_bio(&fio);
 | 
			
		||||
 | 
			
		||||
	if (!err)
 | 
			
		||||
		f2fs_update_iostat(sbi, FS_NODE_READ_IO, F2FS_BLKSIZE);
 | 
			
		||||
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -781,9 +781,9 @@ void f2fs_record_iostat(struct f2fs_sb_info *sbi)
 | 
			
		|||
				msecs_to_jiffies(sbi->iostat_period_ms);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < NR_IO_TYPE; i++) {
 | 
			
		||||
		iostat_diff[i] = sbi->write_iostat[i] -
 | 
			
		||||
				sbi->prev_write_iostat[i];
 | 
			
		||||
		sbi->prev_write_iostat[i] = sbi->write_iostat[i];
 | 
			
		||||
		iostat_diff[i] = sbi->rw_iostat[i] -
 | 
			
		||||
				sbi->prev_rw_iostat[i];
 | 
			
		||||
		sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock(&sbi->iostat_lock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -802,33 +802,51 @@ static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
 | 
			
		|||
 | 
			
		||||
	seq_printf(seq, "time:		%-16llu\n", now);
 | 
			
		||||
 | 
			
		||||
	/* print app IOs */
 | 
			
		||||
	/* print app write IOs */
 | 
			
		||||
	seq_printf(seq, "app buffered:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[APP_BUFFERED_IO]);
 | 
			
		||||
				sbi->rw_iostat[APP_BUFFERED_IO]);
 | 
			
		||||
	seq_printf(seq, "app direct:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[APP_DIRECT_IO]);
 | 
			
		||||
				sbi->rw_iostat[APP_DIRECT_IO]);
 | 
			
		||||
	seq_printf(seq, "app mapped:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[APP_MAPPED_IO]);
 | 
			
		||||
				sbi->rw_iostat[APP_MAPPED_IO]);
 | 
			
		||||
 | 
			
		||||
	/* print fs IOs */
 | 
			
		||||
	/* print fs write IOs */
 | 
			
		||||
	seq_printf(seq, "fs data:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_DATA_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_DATA_IO]);
 | 
			
		||||
	seq_printf(seq, "fs node:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_NODE_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_NODE_IO]);
 | 
			
		||||
	seq_printf(seq, "fs meta:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_META_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_META_IO]);
 | 
			
		||||
	seq_printf(seq, "fs gc data:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_GC_DATA_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_GC_DATA_IO]);
 | 
			
		||||
	seq_printf(seq, "fs gc node:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_GC_NODE_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_GC_NODE_IO]);
 | 
			
		||||
	seq_printf(seq, "fs cp data:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_CP_DATA_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_CP_DATA_IO]);
 | 
			
		||||
	seq_printf(seq, "fs cp node:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_CP_NODE_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_CP_NODE_IO]);
 | 
			
		||||
	seq_printf(seq, "fs cp meta:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_CP_META_IO]);
 | 
			
		||||
				sbi->rw_iostat[FS_CP_META_IO]);
 | 
			
		||||
 | 
			
		||||
	/* print app read IOs */
 | 
			
		||||
	seq_printf(seq, "app buffered:	%-16llu\n",
 | 
			
		||||
				sbi->rw_iostat[APP_BUFFERED_READ_IO]);
 | 
			
		||||
	seq_printf(seq, "app direct:	%-16llu\n",
 | 
			
		||||
				sbi->rw_iostat[APP_DIRECT_READ_IO]);
 | 
			
		||||
	seq_printf(seq, "app mapped:	%-16llu\n",
 | 
			
		||||
				sbi->rw_iostat[APP_MAPPED_READ_IO]);
 | 
			
		||||
 | 
			
		||||
	/* print fs read IOs */
 | 
			
		||||
	seq_printf(seq, "fs data:	%-16llu\n",
 | 
			
		||||
				sbi->rw_iostat[FS_DATA_READ_IO]);
 | 
			
		||||
	seq_printf(seq, "fs node:	%-16llu\n",
 | 
			
		||||
				sbi->rw_iostat[FS_NODE_READ_IO]);
 | 
			
		||||
	seq_printf(seq, "fs meta:	%-16llu\n",
 | 
			
		||||
				sbi->rw_iostat[FS_META_READ_IO]);
 | 
			
		||||
 | 
			
		||||
	/* print other IOs */
 | 
			
		||||
	seq_printf(seq, "fs discard:	%-16llu\n",
 | 
			
		||||
				sbi->write_iostat[FS_DISCARD]);
 | 
			
		||||
				sbi->rw_iostat[FS_DISCARD]);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1832,6 +1832,13 @@ TRACE_EVENT(f2fs_iostat,
 | 
			
		|||
		__field(unsigned long long,	fs_cp_dio)
 | 
			
		||||
		__field(unsigned long long,	fs_cp_nio)
 | 
			
		||||
		__field(unsigned long long,	fs_cp_mio)
 | 
			
		||||
		__field(unsigned long long,	app_drio)
 | 
			
		||||
		__field(unsigned long long,	app_brio)
 | 
			
		||||
		__field(unsigned long long,	app_rio)
 | 
			
		||||
		__field(unsigned long long,	app_mrio)
 | 
			
		||||
		__field(unsigned long long,	fs_drio)
 | 
			
		||||
		__field(unsigned long long,	fs_nrio)
 | 
			
		||||
		__field(unsigned long long,	fs_mrio)
 | 
			
		||||
		__field(unsigned long long,	fs_discard)
 | 
			
		||||
	),
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1849,6 +1856,13 @@ TRACE_EVENT(f2fs_iostat,
 | 
			
		|||
		__entry->fs_cp_dio	= iostat[FS_CP_DATA_IO];
 | 
			
		||||
		__entry->fs_cp_nio	= iostat[FS_CP_NODE_IO];
 | 
			
		||||
		__entry->fs_cp_mio	= iostat[FS_CP_META_IO];
 | 
			
		||||
		__entry->app_drio	= iostat[APP_DIRECT_READ_IO];
 | 
			
		||||
		__entry->app_brio	= iostat[APP_BUFFERED_READ_IO];
 | 
			
		||||
		__entry->app_rio	= iostat[APP_READ_IO];
 | 
			
		||||
		__entry->app_mrio	= iostat[APP_MAPPED_READ_IO];
 | 
			
		||||
		__entry->fs_drio	= iostat[FS_DATA_READ_IO];
 | 
			
		||||
		__entry->fs_nrio	= iostat[FS_NODE_READ_IO];
 | 
			
		||||
		__entry->fs_mrio	= iostat[FS_META_READ_IO];
 | 
			
		||||
		__entry->fs_discard	= iostat[FS_DISCARD];
 | 
			
		||||
	),
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1856,12 +1870,17 @@ TRACE_EVENT(f2fs_iostat,
 | 
			
		|||
		"app [write=%llu (direct=%llu, buffered=%llu), mapped=%llu], "
 | 
			
		||||
		"fs [data=%llu, node=%llu, meta=%llu, discard=%llu], "
 | 
			
		||||
		"gc [data=%llu, node=%llu], "
 | 
			
		||||
		"cp [data=%llu, node=%llu, meta=%llu]",
 | 
			
		||||
		"cp [data=%llu, node=%llu, meta=%llu], "
 | 
			
		||||
		"app [read=%llu (direct=%llu, buffered=%llu), mapped=%llu], "
 | 
			
		||||
		"fs [data=%llu, node=%llu, meta=%llu]",
 | 
			
		||||
		show_dev(__entry->dev), __entry->app_wio, __entry->app_dio,
 | 
			
		||||
		__entry->app_bio, __entry->app_mio, __entry->fs_dio,
 | 
			
		||||
		__entry->fs_nio, __entry->fs_mio, __entry->fs_discard,
 | 
			
		||||
		__entry->fs_gc_dio, __entry->fs_gc_nio, __entry->fs_cp_dio,
 | 
			
		||||
		__entry->fs_cp_nio, __entry->fs_cp_mio)
 | 
			
		||||
		__entry->fs_cp_nio, __entry->fs_cp_mio,
 | 
			
		||||
		__entry->app_rio, __entry->app_drio, __entry->app_brio,
 | 
			
		||||
		__entry->app_mrio, __entry->fs_drio, __entry->fs_nrio,
 | 
			
		||||
		__entry->fs_mrio)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#endif /* _TRACE_F2FS_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue