aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2007-05-11 01:22:37 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-11 11:29:34 -0400
commit6eaeeaba39e5fa3d52a0bb8de15e995516ae251a (patch)
tree5b4052fabfe107ad5332cb758ad8d86ea5a87848
parent02239c29967418284c05d58971894d658575e78c (diff)
getrusage(): fill ru_inblock and ru_oublock fields if possible
If CONFIG_TASK_IO_ACCOUNTING is defined, we update io accounting counters for each task. This patch permits reporting of values using the well known getrusage() syscall, filling ru_inblock and ru_oublock instead of null values. As TASK_IO_ACCOUNTING currently counts bytes counts, we approximate blocks count doing : nr_blocks = nr_bytes / 512 Example of use : ---------------------- After patch is applied, /usr/bin/time command can now give a good approximation of IO that the process had to do. $ /usr/bin/time grep tototo /usr/include/* Command exited with non-zero status 1 0.00user 0.02system 0:02.11elapsed 1%CPU (0avgtext+0avgdata 0maxresident)k 24288inputs+0outputs (0major+259minor)pagefaults 0swaps $ /usr/bin/time dd if=/dev/zero of=/tmp/testfile count=1000 1000+0 enregistrements lus 1000+0 enregistrements écrits 512000 octets (512 kB) copiés, 0,00326601 seconde, 157 MB/s 0.00user 0.00system 0:00.00elapsed 80%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+3000outputs (0major+299minor)pagefaults 0swaps Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/task_io_accounting_ops.h28
-rw-r--r--kernel/exit.c9
-rw-r--r--kernel/fork.c1
-rw-r--r--kernel/sys.c7
5 files changed, 46 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 17b72d88c4c..75f44379b7e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -469,6 +469,7 @@ struct signal_struct {
469 cputime_t utime, stime, cutime, cstime; 469 cputime_t utime, stime, cutime, cstime;
470 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; 470 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
471 unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; 471 unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
472 unsigned long inblock, oublock, cinblock, coublock;
472 473
473 /* 474 /*
474 * Cumulative ns of scheduled CPU time for dead threads in the 475 * Cumulative ns of scheduled CPU time for dead threads in the
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index df2a319106b..1218733ec6b 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -10,11 +10,29 @@ static inline void task_io_account_read(size_t bytes)
10 current->ioac.read_bytes += bytes; 10 current->ioac.read_bytes += bytes;
11} 11}
12 12
13/*
14 * We approximate number of blocks, because we account bytes only.
15 * A 'block' is 512 bytes
16 */
17static inline unsigned long task_io_get_inblock(const struct task_struct *p)
18{
19 return p->ioac.read_bytes >> 9;
20}
21
13static inline void task_io_account_write(size_t bytes) 22static inline void task_io_account_write(size_t bytes)
14{ 23{
15 current->ioac.write_bytes += bytes; 24 current->ioac.write_bytes += bytes;
16} 25}
17 26
27/*
28 * We approximate number of blocks, because we account bytes only.
29 * A 'block' is 512 bytes
30 */
31static inline unsigned long task_io_get_oublock(const struct task_struct *p)
32{
33 return p->ioac.write_bytes >> 9;
34}
35
18static inline void task_io_account_cancelled_write(size_t bytes) 36static inline void task_io_account_cancelled_write(size_t bytes)
19{ 37{
20 current->ioac.cancelled_write_bytes += bytes; 38 current->ioac.cancelled_write_bytes += bytes;
@@ -31,10 +49,20 @@ static inline void task_io_account_read(size_t bytes)
31{ 49{
32} 50}
33 51
52static inline unsigned long task_io_get_inblock(const struct task_struct *p)
53{
54 return 0;
55}
56
34static inline void task_io_account_write(size_t bytes) 57static inline void task_io_account_write(size_t bytes)
35{ 58{
36} 59}
37 60
61static inline unsigned long task_io_get_oublock(const struct task_struct *p)
62{
63 return 0;
64}
65
38static inline void task_io_account_cancelled_write(size_t bytes) 66static inline void task_io_account_cancelled_write(size_t bytes)
39{ 67{
40} 68}
diff --git a/kernel/exit.c b/kernel/exit.c
index b0c6f0c3a2d..7a5fd77f8fb 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -42,6 +42,7 @@
42#include <linux/audit.h> /* for audit_free() */ 42#include <linux/audit.h> /* for audit_free() */
43#include <linux/resource.h> 43#include <linux/resource.h>
44#include <linux/blkdev.h> 44#include <linux/blkdev.h>
45#include <linux/task_io_accounting_ops.h>
45 46
46#include <asm/uaccess.h> 47#include <asm/uaccess.h>
47#include <asm/unistd.h> 48#include <asm/unistd.h>
@@ -113,6 +114,8 @@ static void __exit_signal(struct task_struct *tsk)
113 sig->nvcsw += tsk->nvcsw; 114 sig->nvcsw += tsk->nvcsw;
114 sig->nivcsw += tsk->nivcsw; 115 sig->nivcsw += tsk->nivcsw;
115 sig->sched_time += tsk->sched_time; 116 sig->sched_time += tsk->sched_time;
117 sig->inblock += task_io_get_inblock(tsk);
118 sig->oublock += task_io_get_oublock(tsk);
116 sig = NULL; /* Marker for below. */ 119 sig = NULL; /* Marker for below. */
117 } 120 }
118 121
@@ -1193,6 +1196,12 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
1193 p->nvcsw + sig->nvcsw + sig->cnvcsw; 1196 p->nvcsw + sig->nvcsw + sig->cnvcsw;
1194 psig->cnivcsw += 1197 psig->cnivcsw +=
1195 p->nivcsw + sig->nivcsw + sig->cnivcsw; 1198 p->nivcsw + sig->nivcsw + sig->cnivcsw;
1199 psig->cinblock +=
1200 task_io_get_inblock(p) +
1201 sig->inblock + sig->cinblock;
1202 psig->coublock +=
1203 task_io_get_oublock(p) +
1204 sig->oublock + sig->coublock;
1196 spin_unlock_irq(&p->parent->sighand->siglock); 1205 spin_unlock_irq(&p->parent->sighand->siglock);
1197 } 1206 }
1198 1207
diff --git a/kernel/fork.c b/kernel/fork.c
index 5dd3979747f..da92e01aba6 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -875,6 +875,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
875 sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; 875 sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
876 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; 876 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
877 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; 877 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
878 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
878 sig->sched_time = 0; 879 sig->sched_time = 0;
879 INIT_LIST_HEAD(&sig->cpu_timers[0]); 880 INIT_LIST_HEAD(&sig->cpu_timers[0]);
880 INIT_LIST_HEAD(&sig->cpu_timers[1]); 881 INIT_LIST_HEAD(&sig->cpu_timers[1]);
diff --git a/kernel/sys.c b/kernel/sys.c
index cdb7e9457ba..ec319bbb0bd 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -29,6 +29,7 @@
29#include <linux/signal.h> 29#include <linux/signal.h>
30#include <linux/cn_proc.h> 30#include <linux/cn_proc.h>
31#include <linux/getcpu.h> 31#include <linux/getcpu.h>
32#include <linux/task_io_accounting_ops.h>
32 33
33#include <linux/compat.h> 34#include <linux/compat.h>
34#include <linux/syscalls.h> 35#include <linux/syscalls.h>
@@ -2082,6 +2083,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
2082 r->ru_nivcsw = p->signal->cnivcsw; 2083 r->ru_nivcsw = p->signal->cnivcsw;
2083 r->ru_minflt = p->signal->cmin_flt; 2084 r->ru_minflt = p->signal->cmin_flt;
2084 r->ru_majflt = p->signal->cmaj_flt; 2085 r->ru_majflt = p->signal->cmaj_flt;
2086 r->ru_inblock = p->signal->cinblock;
2087 r->ru_oublock = p->signal->coublock;
2085 2088
2086 if (who == RUSAGE_CHILDREN) 2089 if (who == RUSAGE_CHILDREN)
2087 break; 2090 break;
@@ -2093,6 +2096,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
2093 r->ru_nivcsw += p->signal->nivcsw; 2096 r->ru_nivcsw += p->signal->nivcsw;
2094 r->ru_minflt += p->signal->min_flt; 2097 r->ru_minflt += p->signal->min_flt;
2095 r->ru_majflt += p->signal->maj_flt; 2098 r->ru_majflt += p->signal->maj_flt;
2099 r->ru_inblock += p->signal->inblock;
2100 r->ru_oublock += p->signal->oublock;
2096 t = p; 2101 t = p;
2097 do { 2102 do {
2098 utime = cputime_add(utime, t->utime); 2103 utime = cputime_add(utime, t->utime);
@@ -2101,6 +2106,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
2101 r->ru_nivcsw += t->nivcsw; 2106 r->ru_nivcsw += t->nivcsw;
2102 r->ru_minflt += t->min_flt; 2107 r->ru_minflt += t->min_flt;
2103 r->ru_majflt += t->maj_flt; 2108 r->ru_majflt += t->maj_flt;
2109 r->ru_inblock += task_io_get_inblock(t);
2110 r->ru_oublock += task_io_get_oublock(t);
2104 t = next_thread(t); 2111 t = next_thread(t);
2105 } while (t != p); 2112 } while (t != p);
2106 break; 2113 break;