Commands
dd command
SeqR: time dd if=/nvme/testfile of=/dev/null bs=1024k iflag=direct
SeqW: time dd if=/dev/zero of=/nvme/testfile bs=1024k count=8192 oflag=direct
[Global]
ioengine=libaio
direct=1
rw=randrw
rwmixread=100 (100% reads), 70 (70% reads 30% writes), 0 (100 writes)
thread=1
norandommap=1
time_base=1
runtime=300s
ramp_time=10s
bs=4k
iodepth=32
Numjobs=1
[test]
filename=/dev/nvme0n1
Block size: 4k
SeqR: fio -filename=/tmp/test2g -direct=1 -rw=read -bs=4k -size=2G -numjobs=64 -runtime=10 -group_reporting -name=file1
SeqW: fio -filename=/tmp/test2g -direct=1 -rw=write -bs=4k -size=2G -numjobs=64 -runtime=10 -group_reporting -name=file1
RndR: fio -filename=/tmp/test2g -direct=1 -rw=randread -bs=4k -size=2G -numjobs=64 -runtime=10 -group_reporting -name=file1
RndW: fio -filename=/tmp/test2g -direct=1 -rw=randwrite -bs=4k -size=2G -numjobs=64 -runtime=10 -group_reporting -name=file1
Block size: 32m
SeqR: fio -filename=/tmp/test2g -direct=1 -rw=read -bs=32m -size=2G -numjobs=16 -runtime=10 -group_reporting -name=file1
SeqW: fio -filename=/tmp/test2g -direct=1 -rw=write -bs=32m -size=2G -numjobs=16 -runtime=10 -group_reporting -name=file1
RndR: fio -filename=/tmp/test2g -direct=1 -rw=randread -bs=32m -size=2G -numjobs=16 -runtime=10 -group_reporting -name=file1
RndW: fio -filename=/tmp/test2g -direct=1 -rw=randwrite -bs=32m -size=2G -numjobs=16 -runtime=10 -group_reporting -name=file1
Links
linux storage stack diagram
https://nvmexpress.org/education/drivers/linux-driver-information/
https://www.thomas-krenn.com/en/wiki/Linux_Storage_Stack_Diagram
aio (linux)
fs/notify/fsnotify.c
__fsnotify_parent()
fsnotify()
send_to_group()
fsnotify_handle_event()
fsnotify_handle_inode_event()
return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie);
include/linux/fsnotify.h
fsnotify_perm()
fsnotify_file()
fsnotify_parent()
__fsnotify_parent()
fs/read_write.c
rw_verify_area()
security_file_permission()
fsnotify_perm()
fs/aio.c
SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
struct iocb __user * __user *, iocbpp)
io_submit_one()
__io_submit_one()
aio_read()
rw_verify_area()
aio_rw_done()
aio_write()
rw_verify_area()
aio_rw_done()
include/linux/syscalls.h
#define SYSCALL_METADATA(sname, nb, ...) \
static const char *types_##sname[] = { \
__MAP(nb,__SC_STR_TDECL,__VA_ARGS__) \
}; \
static const char *args_##sname[] = { \
__MAP(nb,__SC_STR_ADECL,__VA_ARGS__) \
}; \
SYSCALL_TRACE_ENTER_EVENT(sname); \
SYSCALL_TRACE_EXIT_EVENT(sname); \
static struct syscall_metadata __used \
__syscall_meta_##sname = { \
.name = "sys"#sname, \
.syscall_nr = -1, /* Filled in at boot */ \
.nb_args = nb, \
.types = nb ? types_##sname : NULL, \
.args = nb ? args_##sname : NULL, \
.enter_event = &event_enter_##sname, \
.exit_event = &event_exit_##sname, \
.enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
}; \
static struct syscall_metadata __used \
__section("__syscalls_metadata") \
*__p_syscall_meta_##sname = &__syscall_meta_##sname;
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINEx(x, sname, ...) \
SYSCALL_METADATA(sname, x, __VA_ARGS__) \
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...) \
__diag_push(); \
__diag_ignore(GCC, 8, "-Wattribute-alias", \
"Type aliasing is used to sanitize syscall arguments");\
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
__attribute__((alias(__stringify(__se_sys##name)))); \
ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \
long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
__MAP(x,__SC_TEST,__VA_ARGS__); \
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
return ret; \
} \
__diag_pop(); \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
Latency
ioengines.c
td_io_queue()
fio_gettime(&io_u->issue_time, NULL);
td_io_commit()
td->io_ops->commit() -> fio_libaio_commit()
engines\libaio.c
fio_libaio_commit()
io_submit()
fio_libaio_queued()
fio_gettime(&now, NULL);
memcpy(&io_u->issue_time, &now, sizeof(now));
backend.c
do_verify()
fio_gettime(&io_u->start_time, NULL);
io_u_submit()
td_io_queue()
fio_io_sync()
td_io_queue()
io_u.c
get_io_u()
fio_gettime(&io_u->start_time, NULL);
io_u_queued()
slat_time = ntime_since(&io_u->start_time, &io_u->issue_time);
add_slat_sample(td, io_u->ddir, slat_time, io_u->xfer_buflen, io_u->offset, io_u_is_prio(io_u));
io_u_queued_complete()
init_icd()
fio_gettime(&icd->time, NULL);
ios_completed()
account_io_completion()
llnsec = ntime_since(&io_u->issue_time, &icd->time);
tnsec = ntime_since(&io_u->start_time, &icd->time);
add_lat_sample(td, idx, tnsec, bytes, io_u->offset, io_u_is_prio(io_u));
add_clat_sample(td, idx, llnsec, bytes, io_u->offset, io_u_is_prio(io_u));
io_u_mark_latency(td, llnsec);
rate-submit.c
io_workqueue_fn()
td_io_queue()