From b2d002dba5a8a4c0c3ec96fd1ff3c9def6bd71a1 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Sat, 26 Jul 2008 15:22:27 -0700 Subject: [PATCH] task IO accounting: correctly account threads IO statistics Oleg Nesterov points out that we should check that the task is still alive before we iterate over the threads. This patch includes a fixup for this. Also simplify do_io_accounting() implementation. Signed-off-by: Andrea Righi Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 54 ++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 81bce6791bfc..d744aa3c9f74 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2406,35 +2406,18 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) u64 rchar, wchar, syscr, syscw; struct task_io_accounting ioac; - if (!whole) { - rchar = task->rchar; - wchar = task->wchar; - syscr = task->syscr; - syscw = task->syscw; - memcpy(&ioac, &task->ioac, sizeof(ioac)); - } else { + rchar = task->rchar; + wchar = task->wchar; + syscr = task->syscr; + syscw = task->syscw; + memcpy(&ioac, &task->ioac, sizeof(ioac)); + + if (whole) { unsigned long flags; - struct task_struct *t = task; - rchar = wchar = syscr = syscw = 0; - memset(&ioac, 0, sizeof(ioac)); - - rcu_read_lock(); - do { - rchar += t->rchar; - wchar += t->wchar; - syscr += t->syscr; - syscw += t->syscw; - - ioac.read_bytes += t->ioac.read_bytes; - ioac.write_bytes += t->ioac.write_bytes; - ioac.cancelled_write_bytes += - t->ioac.cancelled_write_bytes; - t = next_thread(t); - } while (t != task); - rcu_read_unlock(); if (lock_task_sighand(task, &flags)) { struct signal_struct *sig = task->signal; + struct task_struct *t = task; rchar += sig->rchar; wchar += sig->wchar; @@ -2445,11 +2428,20 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) ioac.write_bytes += sig->ioac.write_bytes; ioac.cancelled_write_bytes += sig->ioac.cancelled_write_bytes; + while_each_thread(task, t) { + rchar += t->rchar; + wchar += t->wchar; + syscr += t->syscr; + syscw += t->syscw; + ioac.read_bytes += t->ioac.read_bytes; + ioac.write_bytes += t->ioac.write_bytes; + ioac.cancelled_write_bytes += + t->ioac.cancelled_write_bytes; + } unlock_task_sighand(task, &flags); } } - return sprintf(buffer, "rchar: %llu\n" "wchar: %llu\n" @@ -2458,13 +2450,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) "read_bytes: %llu\n" "write_bytes: %llu\n" "cancelled_write_bytes: %llu\n", - (unsigned long long)rchar, - (unsigned long long)wchar, - (unsigned long long)syscr, - (unsigned long long)syscw, - (unsigned long long)ioac.read_bytes, - (unsigned long long)ioac.write_bytes, - (unsigned long long)ioac.cancelled_write_bytes); + rchar, wchar, syscr, syscw, + ioac.read_bytes, ioac.write_bytes, + ioac.cancelled_write_bytes); } static int proc_tid_io_accounting(struct task_struct *task, char *buffer)