diff options
author | Andrea Righi <righi.andrea@gmail.com> | 2008-07-25 04:48:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:47 -0400 |
commit | 297c5d92634c809cef23d73e7b2556f2528ff7e2 (patch) | |
tree | d006fa29daa24242c64cff3b66dd75fbb0003b0f /kernel/exit.c | |
parent | 0c18d7a5df82524e634637c3aec24d4cba096442 (diff) |
task IO accounting: provide distinct tgid/tid I/O statistics
Report per-thread I/O statistics in /proc/pid/task/tid/io and aggregate
parent I/O statistics in /proc/pid/io. This approach follows the same
model used to account per-process and per-thread CPU times.
As a practial application, this allows for example to quickly find the top
I/O consumer when a process spawns many child threads that perform the
actual I/O work, because the aggregated I/O statistics can always be found
in /proc/pid/io.
[ Oleg Nesterov points out that we should check that the task is still
alive before we iterate over the threads, but also says that we can do
that fixup on top of this later. - Linus ]
Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Signed-off-by: Andrea Righi <righi.andrea@gmail.com>
Cc: Matt Heaton <matt@hostmonster.com>
Cc: Shailabh Nagar <nagar@watson.ibm.com>
Acked-by-with-comments: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 8a4d4d12e294..ad933bb29ec7 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -120,6 +120,18 @@ static void __exit_signal(struct task_struct *tsk) | |||
120 | sig->nivcsw += tsk->nivcsw; | 120 | sig->nivcsw += tsk->nivcsw; |
121 | sig->inblock += task_io_get_inblock(tsk); | 121 | sig->inblock += task_io_get_inblock(tsk); |
122 | sig->oublock += task_io_get_oublock(tsk); | 122 | sig->oublock += task_io_get_oublock(tsk); |
123 | #ifdef CONFIG_TASK_XACCT | ||
124 | sig->rchar += tsk->rchar; | ||
125 | sig->wchar += tsk->wchar; | ||
126 | sig->syscr += tsk->syscr; | ||
127 | sig->syscw += tsk->syscw; | ||
128 | #endif /* CONFIG_TASK_XACCT */ | ||
129 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
130 | sig->ioac.read_bytes += tsk->ioac.read_bytes; | ||
131 | sig->ioac.write_bytes += tsk->ioac.write_bytes; | ||
132 | sig->ioac.cancelled_write_bytes += | ||
133 | tsk->ioac.cancelled_write_bytes; | ||
134 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
123 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; | 135 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; |
124 | sig = NULL; /* Marker for below. */ | 136 | sig = NULL; /* Marker for below. */ |
125 | } | 137 | } |
@@ -1366,6 +1378,21 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1366 | psig->coublock += | 1378 | psig->coublock += |
1367 | task_io_get_oublock(p) + | 1379 | task_io_get_oublock(p) + |
1368 | sig->oublock + sig->coublock; | 1380 | sig->oublock + sig->coublock; |
1381 | #ifdef CONFIG_TASK_XACCT | ||
1382 | psig->rchar += p->rchar + sig->rchar; | ||
1383 | psig->wchar += p->wchar + sig->wchar; | ||
1384 | psig->syscr += p->syscr + sig->syscr; | ||
1385 | psig->syscw += p->syscw + sig->syscw; | ||
1386 | #endif /* CONFIG_TASK_XACCT */ | ||
1387 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
1388 | psig->ioac.read_bytes += | ||
1389 | p->ioac.read_bytes + sig->ioac.read_bytes; | ||
1390 | psig->ioac.write_bytes += | ||
1391 | p->ioac.write_bytes + sig->ioac.write_bytes; | ||
1392 | psig->ioac.cancelled_write_bytes += | ||
1393 | p->ioac.cancelled_write_bytes + | ||
1394 | sig->ioac.cancelled_write_bytes; | ||
1395 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
1369 | spin_unlock_irq(&p->parent->sighand->siglock); | 1396 | spin_unlock_irq(&p->parent->sighand->siglock); |
1370 | } | 1397 | } |
1371 | 1398 | ||