FIO是通用的测试系统IO的工具,其同样可以适用于Flash设备。
写测试命令:
fio -rw=trimwrite -ioengine=mtd -bs=64k -size=64k -numjobs=1 -group_reporting -filename=/dev/mtd4 --verify=md5 -name=Write_BandWidth_Test
读测试命令:
fio -rw=read -ioengine=mtd -bs=64k -size=10M -numjobs=1 -group_reporting -filename=/dev/mtd4 --readonly -name=Read_BandWidth_Test
命令参数
-rw 读写方向,其中trimwrite对于ioengine为mtd时表示先擦后写,具体代码如下:
trim
Sequential trims (Linux block devices and SCSI character devices only).
randtrim
Random trims (Linux block devices and SCSI character devices only).
-ioengine io引擎,表示不同的触发IO的方式,这里我们使用为MTD设备开发的mtd ioengine
-bs block size,表示块设备的固有属性,块的大小
-size 具体测试的数据大小,大小达到size后测试会自动停止
-numjob 表示每次测试的线程数量,用于模拟多线程应用场景
-group_reporting 一般用于多线程场景使用,如果不使用且numjob大于1,则会打印每个线程的测试结果,导致log过多,使用这个选项后会统一到一个report中
-filename 表示测试的具体文件,这里我们使用/dev/mtd
--readonly 表示强调只读,防止误操作写动作
-name 表示每次测试的名字,方便后续查看log
--verify 表示验证上一次写动作的正确性
工具源码:
fio源码
fio/engines/mtd.c
static enum fio_q_status fio_mtd_queue(struct thread_data *td,
struct io_u *io_u)
{
...
} else if (io_u->ddir == DDIR_WRITE) {
ret = mtd_write(desc, &fmd->info, f->fd, eb,
eb_offs, buf, len, NULL, 0, 0);
if (ret != 0) {
io_u->error = errno;
td_verror(td, errno, "mtd_write");
if (fio_mtd_maybe_mark_bad(td, fmd, io_u, eb))
break;
}
...
}
fio/fio/ioengines.c
enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u)
{
}
fio/backend.c
static enum fio_q_status io_u_submit(struct thread_data *td, struct io_u *io_u)
{
/*
* Check for overlap if the user asked us to, and we have
* at least one IO in flight besides this one.
*/
if (td->o.serialize_overlap && td->cur_depth > 1 &&
in_flight_overlap(&td->io_u_all, io_u))
return FIO_Q_BUSY;
return td_io_queue(td, io_u);
}
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
*
* Returns number of bytes written and trimmed.
*/
static void do_io(struct thread_data *td, uint64_t *bytes_done)
{
ret = io_u_submit(td, io_u);
}
/*
* Entry point for the thread based jobs. The process based jobs end up
* here as well, after a little setup.
*/
static void *thread_main(void *data)
{
do_io(td, bytes_done);
}
int main(int argc, char *argv[], char *envp[])
fio_backend
run_threads
thread_main
verify代码逻辑
fio/backend.c
/*
* The main verify engine. Runs over the writes we previously submitted,
* reads the blocks back in, and checks the crc/md5 of the data.
*/
static void do_verify(struct thread_data *td, uint64_t verify_bytes)
{
参考文档: