trace: add last read file to sched_stat_iowait
RFC PATCH 1/1 trace: add last read file to sched_stat_iowait
This is a lighter weight, but potentially imprecise way of figuring out which files are responsible for a process to enter iowait.
It only keeps track of read code paths (vfs_read) and ignores writeback related iowaits.
Sample output:
localhost ~ # perf record -ae sched:sched_stat_iowait -- sleep 10 & <do some io>
localhosfd~ # perf script
swapper 0 [000] 176.082523: sched_stat_iowait: comm=cat pid=1387 delay=1362 [ns] ino=116899
swapper 0 [000] 176.082523: sched_stat_iowait: comm=cat pid=1387 delay=1362 [ns] ino=116899
swapper 0 [000] 176.082523: sched_stat_iowait: comm=cat pid=1387 delay=1362 [ns] ino=116899localhost ~ # find /usr -inum 116899/usr/tests/sets/files/testStaticFileSet.py
Signed-off-by Arun Sharma <[email protected]>
Cc Tejun Heo <[email protected]>
Cc Namhyung Kim <[email protected]>
fs/file.c +1 -0
@@ -304,6 +304,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)spin_lock_init (&newf->file_lock); newf->next_fd =0 ; + newf->last_read =NULL ; new_fdt = &newf->fdtab; new_fdt->max_fds =NR_OPEN_DEFAULT ; new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init;
fs/read_write.c +3 -0
@@ -8,6 +8,7 @@#include <linux/stat.h> #include <linux/fcntl.h> #include <linux/file.h> +#include <linux/fdtable.h> #include <linux/uio.h> #include <linux/fsnotify.h> #include <linux/security.h>
@@ -375,6 +376,8 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) ret =rw_verify_area (READ , file, pos, count);if (ret >=0 ) { count = ret; +if (current->files) + current->files->last_read = file;if (file->f_op->read) ret = file->f_op->read (file, buf, count, pos);else
include/linux/fdtable.h +1 -0
@@ -53,6 +53,7 @@ struct files_struct {*/ spinlock_t file_lock____cacheline_aligned_in_smp ;int next_fd; +struct file *last_read;struct embedded_fd_set close_on_exec_init;struct embedded_fd_set open_fds_init;struct file __rcu * fd_array[NR_OPEN_DEFAULT ];
include/trace/events/sched.h +35 -3
@@ -326,9 +326,41 @@ DEFINE_EVENT(sched_stat_template, sched_stat_sleep,* Tracepoint for accounting iowait time (time the task is not runnable * due to waiting on IO to complete). */ -DEFINE_EVENT (sched_stat_template, sched_stat_iowait, - TP_PROTO(struct task_struct *tsk, u64 delay), -TP_ARGS (tsk, delay)); +TRACE_EVENT (sched_stat_iowait, + + TP_PROTO(struct task_struct *tsk, u64 delay, struct file *file), + +TP_ARGS (tsk, delay, file), + +TP_STRUCT__entry ( + __array( char, comm, TASK_COMM_LEN ) + __field( pid_t, pid ) + __field( u64, delay ) +__field ( ino_t, ino ) + ), + +TP_fast_assign ( + memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN); + __entry->pid = tsk->pid; + __entry->delay = delay; + if (file) { +struct dentry *dentry = file->f_path.dentry; +struct inode *inode =NULL ; +if (dentry) + inode = dentry->d_inode; +if (inode) + __entry->ino = inode->i_ino; + } + ) + TP_perf_assign( + __perf_count(delay); + ), + +TP_printk ("comm=%s pid=%d delay=%Lu [ns] ino=%ld" , + __entry->comm, __entry->pid, + (unsigned long long )__entry->delay, + (unsigned long ) __entry->ino) +);/* * Tracepoint for accounting blocked time (time the task is in uninterruptible).
kernel/sched/fair.c +5 -1
@@ -26,6 +26,7 @@#include <linux/slab.h> #include <linux/profile.h> #include <linux/interrupt.h> +#include <linux/fdtable.h> #include <trace/events/sched.h>
@@ -1025,9 +1026,12 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)if (tsk) {if (tsk->in_iowait) { +struct file *last_read_file =NULL ; +if (tsk->files) + last_read_file = tsk->files->last_read; se->statistics.iowait_sum += delta; se->statistics.iowait_count++; -trace_sched_stat_iowait (tsk, delta); +trace_sched_stat_iowait (tsk, delta, last_read_file); }trace_sched_stat_blocked (tsk, delta);