Per-process I/O stats in Linux - TASKSTATS_CMD_ATTR_TGID not working

312 views Asked by At

Linux provides /proc/[pid]/io interface to get I/O stats of a process. But in addition to the accumulated I/O of live threads, read_bytes and write_bytes fields also include the I/O of dead threads and dead children of the process (because fork() and exit() occur both for processes and threads; details here).

So to get the accumulated I/O of live threads only, one can sum the stats from /proc/[pid]/task/[tid]/io interface. Another way to achieve the same is to use the netlink-based taskstats interface (using TASKSTATS_CMD_ATTR_PID command).

But to get the per-process I/O stats of all living and dead threads of a process (excluding the I/O of dead child processes), one expects to use the per-tgid stats interface (with TASKSTATS_CMD_ATTR_TGID command):

per-tgid stats

...

When a user queries to get per-tgid data, the sum of all other live threads in the group is added up and added to the accumulated total for previously exited threads of the same thread group.

But this is not true for I/O stats. In the kernel source code, extended accounting fields (which include I/O stats) are filled only when preparing taskstats struct for threads (pid), not for whole process (tgid).

Also the getdelays utility itself states:

getdelays [-i] [-t tgid] [-p pid]

-i: print IO accounting (works only with -p)

Which means that I/O stats are returned only per-thread (with -p option), not per-process (with -t option). If we try with TASKSTATS_CMD_ATTR_TGID, read_bytes and write_bytes simply return zero. The same is true when listening to exit stats of threads / processes (with TASKSTATS_CMD_ATTR_REGISTER).

Is there a way to get per-process I/O stats of all live and exited threads of a process?

1

There are 1 answers

2
Ali Bahrami On

Linux kernel doesn't currently support per-process I/O statistics for both live and dead threads of a process via the TASKSTATS_CMD_ATTR_TGID command. A manual approach is required.

You may need to modify the Linux kernel to add this support.

Here's a rough pseudocode:

Extend the taskstats structure in taskstats.h:

struct taskstats {
    ...
    __u64 read_bytes;
    __u64 write_bytes;
    ...
};

Add up the I/O stats when a thread exits in exit.c:

do_exit(long code) {
    ...
    p->parent->read_bytes += p->io_context->read_bytes;
    p->parent->write_bytes += p->io_context->write_bytes;
    ...
}

Include the accumulated I/O stats in the taskstats structure in taskstats.c:

fill_tgid_exit(struct task_struct *tsk) {
    ...
    stats->read_bytes = tsk->read_bytes;
    stats->write_bytes = tsk->write_bytes;
    ...
}

This is a simplified version and real implementation would be complex. A lot things are to be considered. Kernel modification requires deep expertise and must be done with caution as it can impact system stability and security. It's suggested to contribute such changes to the Linux community for peer review.