aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c57
-rw-r--r--include/linux/sched.h19
-rw-r--r--include/linux/task_io_accounting.h27
-rw-r--r--include/linux/task_io_accounting_ops.h56
-rw-r--r--kernel/exit.c30
-rw-r--r--kernel/fork.c15
-rw-r--r--kernel/tsacct.c14
7 files changed, 104 insertions, 114 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e74308bdabd3..3d94906c7aa8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -53,6 +53,7 @@
53#include <linux/time.h> 53#include <linux/time.h>
54#include <linux/proc_fs.h> 54#include <linux/proc_fs.h>
55#include <linux/stat.h> 55#include <linux/stat.h>
56#include <linux/task_io_accounting_ops.h>
56#include <linux/init.h> 57#include <linux/init.h>
57#include <linux/capability.h> 58#include <linux/capability.h>
58#include <linux/file.h> 59#include <linux/file.h>
@@ -2402,44 +2403,17 @@ static int proc_base_fill_cache(struct file *filp, void *dirent,
2402#ifdef CONFIG_TASK_IO_ACCOUNTING 2403#ifdef CONFIG_TASK_IO_ACCOUNTING
2403static int do_io_accounting(struct task_struct *task, char *buffer, int whole) 2404static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
2404{ 2405{
2405 u64 rchar, wchar, syscr, syscw; 2406 struct proc_io_accounting acct = task->ioac;
2406 struct task_io_accounting ioac; 2407 unsigned long flags;
2407 2408
2408 rchar = task->rchar; 2409 if (whole && lock_task_sighand(task, &flags)) {
2409 wchar = task->wchar; 2410 struct task_struct *t = task;
2410 syscr = task->syscr; 2411
2411 syscw = task->syscw; 2412 task_io_accounting_add(&acct, &task->signal->ioac);
2412 memcpy(&ioac, &task->ioac, sizeof(ioac)); 2413 while_each_thread(task, t)
2413 2414 task_io_accounting_add(&acct, &t->ioac);
2414 if (whole) { 2415
2415 unsigned long flags; 2416 unlock_task_sighand(task, &flags);
2416
2417 if (lock_task_sighand(task, &flags)) {
2418 struct signal_struct *sig = task->signal;
2419 struct task_struct *t = task;
2420
2421 rchar += sig->rchar;
2422 wchar += sig->wchar;
2423 syscr += sig->syscr;
2424 syscw += sig->syscw;
2425
2426 ioac.read_bytes += sig->ioac.read_bytes;
2427 ioac.write_bytes += sig->ioac.write_bytes;
2428 ioac.cancelled_write_bytes +=
2429 sig->ioac.cancelled_write_bytes;
2430 while_each_thread(task, t) {
2431 rchar += t->rchar;
2432 wchar += t->wchar;
2433 syscr += t->syscr;
2434 syscw += t->syscw;
2435
2436 ioac.read_bytes += t->ioac.read_bytes;
2437 ioac.write_bytes += t->ioac.write_bytes;
2438 ioac.cancelled_write_bytes +=
2439 t->ioac.cancelled_write_bytes;
2440 }
2441 unlock_task_sighand(task, &flags);
2442 }
2443 } 2417 }
2444 return sprintf(buffer, 2418 return sprintf(buffer,
2445 "rchar: %llu\n" 2419 "rchar: %llu\n"
@@ -2449,9 +2423,10 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
2449 "read_bytes: %llu\n" 2423 "read_bytes: %llu\n"
2450 "write_bytes: %llu\n" 2424 "write_bytes: %llu\n"
2451 "cancelled_write_bytes: %llu\n", 2425 "cancelled_write_bytes: %llu\n",
2452 rchar, wchar, syscr, syscw, 2426 acct.chr.rchar, acct.chr.wchar,
2453 ioac.read_bytes, ioac.write_bytes, 2427 acct.chr.syscr, acct.chr.syscw,
2454 ioac.cancelled_write_bytes); 2428 acct.blk.read_bytes, acct.blk.write_bytes,
2429 acct.blk.cancelled_write_bytes);
2455} 2430}
2456 2431
2457static int proc_tid_io_accounting(struct task_struct *task, char *buffer) 2432static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f59318a0099b..034c1ca6b332 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -505,10 +505,7 @@ struct signal_struct {
505 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; 505 unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
506 unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; 506 unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
507 unsigned long inblock, oublock, cinblock, coublock; 507 unsigned long inblock, oublock, cinblock, coublock;
508#ifdef CONFIG_TASK_XACCT 508 struct proc_io_accounting ioac;
509 u64 rchar, wchar, syscr, syscw;
510#endif
511 struct task_io_accounting ioac;
512 509
513 /* 510 /*
514 * Cumulative ns of scheduled CPU time for dead threads in the 511 * Cumulative ns of scheduled CPU time for dead threads in the
@@ -1256,11 +1253,7 @@ struct task_struct {
1256 1253
1257 unsigned long ptrace_message; 1254 unsigned long ptrace_message;
1258 siginfo_t *last_siginfo; /* For ptrace use. */ 1255 siginfo_t *last_siginfo; /* For ptrace use. */
1259#ifdef CONFIG_TASK_XACCT 1256 struct proc_io_accounting ioac;
1260/* i/o counters(bytes read/written, #syscalls */
1261 u64 rchar, wchar, syscr, syscw;
1262#endif
1263 struct task_io_accounting ioac;
1264#if defined(CONFIG_TASK_XACCT) 1257#if defined(CONFIG_TASK_XACCT)
1265 u64 acct_rss_mem1; /* accumulated rss usage */ 1258 u64 acct_rss_mem1; /* accumulated rss usage */
1266 u64 acct_vm_mem1; /* accumulated virtual memory usage */ 1259 u64 acct_vm_mem1; /* accumulated virtual memory usage */
@@ -2190,22 +2183,22 @@ extern long sched_group_rt_period(struct task_group *tg);
2190#ifdef CONFIG_TASK_XACCT 2183#ifdef CONFIG_TASK_XACCT
2191static inline void add_rchar(struct task_struct *tsk, ssize_t amt) 2184static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
2192{ 2185{
2193 tsk->rchar += amt; 2186 tsk->ioac.chr.rchar += amt;
2194} 2187}
2195 2188
2196static inline void add_wchar(struct task_struct *tsk, ssize_t amt) 2189static inline void add_wchar(struct task_struct *tsk, ssize_t amt)
2197{ 2190{
2198 tsk->wchar += amt; 2191 tsk->ioac.chr.wchar += amt;
2199} 2192}
2200 2193
2201static inline void inc_syscr(struct task_struct *tsk) 2194static inline void inc_syscr(struct task_struct *tsk)
2202{ 2195{
2203 tsk->syscr++; 2196 tsk->ioac.chr.syscr++;
2204} 2197}
2205 2198
2206static inline void inc_syscw(struct task_struct *tsk) 2199static inline void inc_syscw(struct task_struct *tsk)
2207{ 2200{
2208 tsk->syscw++; 2201 tsk->ioac.chr.syscw++;
2209} 2202}
2210#else 2203#else
2211static inline void add_rchar(struct task_struct *tsk, ssize_t amt) 2204static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
diff --git a/include/linux/task_io_accounting.h b/include/linux/task_io_accounting.h
index 44d00e9cceea..165390f8b936 100644
--- a/include/linux/task_io_accounting.h
+++ b/include/linux/task_io_accounting.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * task_io_accounting: a structure which is used for recording a single task's 2 * proc_io_accounting: a structure which is used for recording a single task's
3 * IO statistics. 3 * IO statistics.
4 * 4 *
5 * Don't include this header file directly - it is designed to be dragged in via 5 * Don't include this header file directly - it is designed to be dragged in via
@@ -8,6 +8,22 @@
8 * Blame akpm@osdl.org for all this. 8 * Blame akpm@osdl.org for all this.
9 */ 9 */
10 10
11#ifdef CONFIG_TASK_XACCT
12struct task_chr_io_accounting {
13 /* bytes read */
14 u64 rchar;
15 /* bytes written */
16 u64 wchar;
17 /* # of read syscalls */
18 u64 syscr;
19 /* # of write syscalls */
20 u64 syscw;
21};
22#else /* CONFIG_TASK_XACCT */
23struct task_chr_io_accounting {
24};
25#endif /* CONFIG_TASK_XACCT */
26
11#ifdef CONFIG_TASK_IO_ACCOUNTING 27#ifdef CONFIG_TASK_IO_ACCOUNTING
12struct task_io_accounting { 28struct task_io_accounting {
13 /* 29 /*
@@ -31,7 +47,12 @@ struct task_io_accounting {
31 */ 47 */
32 u64 cancelled_write_bytes; 48 u64 cancelled_write_bytes;
33}; 49};
34#else 50#else /* CONFIG_TASK_IO_ACCOUNTING */
35struct task_io_accounting { 51struct task_io_accounting {
36}; 52};
37#endif 53#endif /* CONFIG_TASK_IO_ACCOUNTING */
54
55struct proc_io_accounting {
56 struct task_chr_io_accounting chr;
57 struct task_io_accounting blk;
58};
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index ff46c6fad79d..e6f958ebe97f 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -9,7 +9,7 @@
9#ifdef CONFIG_TASK_IO_ACCOUNTING 9#ifdef CONFIG_TASK_IO_ACCOUNTING
10static inline void task_io_account_read(size_t bytes) 10static inline void task_io_account_read(size_t bytes)
11{ 11{
12 current->ioac.read_bytes += bytes; 12 current->ioac.blk.read_bytes += bytes;
13} 13}
14 14
15/* 15/*
@@ -18,12 +18,12 @@ static inline void task_io_account_read(size_t bytes)
18 */ 18 */
19static inline unsigned long task_io_get_inblock(const struct task_struct *p) 19static inline unsigned long task_io_get_inblock(const struct task_struct *p)
20{ 20{
21 return p->ioac.read_bytes >> 9; 21 return p->ioac.blk.read_bytes >> 9;
22} 22}
23 23
24static inline void task_io_account_write(size_t bytes) 24static inline void task_io_account_write(size_t bytes)
25{ 25{
26 current->ioac.write_bytes += bytes; 26 current->ioac.blk.write_bytes += bytes;
27} 27}
28 28
29/* 29/*
@@ -32,17 +32,25 @@ static inline void task_io_account_write(size_t bytes)
32 */ 32 */
33static inline unsigned long task_io_get_oublock(const struct task_struct *p) 33static inline unsigned long task_io_get_oublock(const struct task_struct *p)
34{ 34{
35 return p->ioac.write_bytes >> 9; 35 return p->ioac.blk.write_bytes >> 9;
36} 36}
37 37
38static inline void task_io_account_cancelled_write(size_t bytes) 38static inline void task_io_account_cancelled_write(size_t bytes)
39{ 39{
40 current->ioac.cancelled_write_bytes += bytes; 40 current->ioac.blk.cancelled_write_bytes += bytes;
41} 41}
42 42
43static inline void task_io_accounting_init(struct task_struct *tsk) 43static inline void task_io_accounting_init(struct proc_io_accounting *ioac)
44{ 44{
45 memset(&tsk->ioac, 0, sizeof(tsk->ioac)); 45 memset(ioac, 0, sizeof(*ioac));
46}
47
48static inline void task_blk_io_accounting_add(struct proc_io_accounting *dst,
49 struct proc_io_accounting *src)
50{
51 dst->blk.read_bytes += src->blk.read_bytes;
52 dst->blk.write_bytes += src->blk.write_bytes;
53 dst->blk.cancelled_write_bytes += src->blk.cancelled_write_bytes;
46} 54}
47 55
48#else 56#else
@@ -69,9 +77,37 @@ static inline void task_io_account_cancelled_write(size_t bytes)
69{ 77{
70} 78}
71 79
72static inline void task_io_accounting_init(struct task_struct *tsk) 80static inline void task_io_accounting_init(struct proc_io_accounting *ioac)
81{
82}
83
84static inline void task_blk_io_accounting_add(struct proc_io_accounting *dst,
85 struct proc_io_accounting *src)
73{ 86{
74} 87}
75 88
76#endif /* CONFIG_TASK_IO_ACCOUNTING */ 89#endif /* CONFIG_TASK_IO_ACCOUNTING */
77#endif /* __TASK_IO_ACCOUNTING_OPS_INCLUDED */ 90
91#ifdef CONFIG_TASK_XACCT
92static inline void task_chr_io_accounting_add(struct proc_io_accounting *dst,
93 struct proc_io_accounting *src)
94{
95 dst->chr.rchar += src->chr.rchar;
96 dst->chr.wchar += src->chr.wchar;
97 dst->chr.syscr += src->chr.syscr;
98 dst->chr.syscw += src->chr.syscw;
99}
100#else
101static inline void task_chr_io_accounting_add(struct proc_io_accounting *dst,
102 struct proc_io_accounting *src)
103{
104}
105#endif /* CONFIG_TASK_XACCT */
106
107static inline void task_io_accounting_add(struct proc_io_accounting *dst,
108 struct proc_io_accounting *src)
109{
110 task_chr_io_accounting_add(dst, src);
111 task_blk_io_accounting_add(dst, src);
112}
113#endif /* __TASK_IO_ACCOUNTING_OPS_INCLUDED */
diff --git a/kernel/exit.c b/kernel/exit.c
index 0caf590548a0..eb4d6470d1d0 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -121,18 +121,7 @@ static void __exit_signal(struct task_struct *tsk)
121 sig->nivcsw += tsk->nivcsw; 121 sig->nivcsw += tsk->nivcsw;
122 sig->inblock += task_io_get_inblock(tsk); 122 sig->inblock += task_io_get_inblock(tsk);
123 sig->oublock += task_io_get_oublock(tsk); 123 sig->oublock += task_io_get_oublock(tsk);
124#ifdef CONFIG_TASK_XACCT 124 task_io_accounting_add(&sig->ioac, &tsk->ioac);
125 sig->rchar += tsk->rchar;
126 sig->wchar += tsk->wchar;
127 sig->syscr += tsk->syscr;
128 sig->syscw += tsk->syscw;
129#endif /* CONFIG_TASK_XACCT */
130#ifdef CONFIG_TASK_IO_ACCOUNTING
131 sig->ioac.read_bytes += tsk->ioac.read_bytes;
132 sig->ioac.write_bytes += tsk->ioac.write_bytes;
133 sig->ioac.cancelled_write_bytes +=
134 tsk->ioac.cancelled_write_bytes;
135#endif /* CONFIG_TASK_IO_ACCOUNTING */
136 sig->sum_sched_runtime += tsk->se.sum_exec_runtime; 125 sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
137 sig = NULL; /* Marker for below. */ 126 sig = NULL; /* Marker for below. */
138 } 127 }
@@ -1363,21 +1352,8 @@ static int wait_task_zombie(struct task_struct *p, int options,
1363 psig->coublock += 1352 psig->coublock +=
1364 task_io_get_oublock(p) + 1353 task_io_get_oublock(p) +
1365 sig->oublock + sig->coublock; 1354 sig->oublock + sig->coublock;
1366#ifdef CONFIG_TASK_XACCT 1355 task_io_accounting_add(&psig->ioac, &p->ioac);
1367 psig->rchar += p->rchar + sig->rchar; 1356 task_io_accounting_add(&psig->ioac, &sig->ioac);
1368 psig->wchar += p->wchar + sig->wchar;
1369 psig->syscr += p->syscr + sig->syscr;
1370 psig->syscw += p->syscw + sig->syscw;
1371#endif /* CONFIG_TASK_XACCT */
1372#ifdef CONFIG_TASK_IO_ACCOUNTING
1373 psig->ioac.read_bytes +=
1374 p->ioac.read_bytes + sig->ioac.read_bytes;
1375 psig->ioac.write_bytes +=
1376 p->ioac.write_bytes + sig->ioac.write_bytes;
1377 psig->ioac.cancelled_write_bytes +=
1378 p->ioac.cancelled_write_bytes +
1379 sig->ioac.cancelled_write_bytes;
1380#endif /* CONFIG_TASK_IO_ACCOUNTING */
1381 spin_unlock_irq(&p->parent->sighand->siglock); 1357 spin_unlock_irq(&p->parent->sighand->siglock);
1382 } 1358 }
1383 1359
diff --git a/kernel/fork.c b/kernel/fork.c
index 5e050c1317c4..8214ba7c8bb1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -806,12 +806,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
806 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; 806 sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
807 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; 807 sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
808 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; 808 sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
809#ifdef CONFIG_TASK_XACCT 809 task_io_accounting_init(&sig->ioac);
810 sig->rchar = sig->wchar = sig->syscr = sig->syscw = 0;
811#endif
812#ifdef CONFIG_TASK_IO_ACCOUNTING
813 memset(&sig->ioac, 0, sizeof(sig->ioac));
814#endif
815 sig->sum_sched_runtime = 0; 810 sig->sum_sched_runtime = 0;
816 INIT_LIST_HEAD(&sig->cpu_timers[0]); 811 INIT_LIST_HEAD(&sig->cpu_timers[0]);
817 INIT_LIST_HEAD(&sig->cpu_timers[1]); 812 INIT_LIST_HEAD(&sig->cpu_timers[1]);
@@ -994,13 +989,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
994 p->last_switch_timestamp = 0; 989 p->last_switch_timestamp = 0;
995#endif 990#endif
996 991
997#ifdef CONFIG_TASK_XACCT 992 task_io_accounting_init(&p->ioac);
998 p->rchar = 0; /* I/O counter: bytes read */
999 p->wchar = 0; /* I/O counter: bytes written */
1000 p->syscr = 0; /* I/O counter: read syscalls */
1001 p->syscw = 0; /* I/O counter: write syscalls */
1002#endif
1003 task_io_accounting_init(p);
1004 acct_clear_integrals(p); 993 acct_clear_integrals(p);
1005 994
1006 p->it_virt_expires = cputime_zero; 995 p->it_virt_expires = cputime_zero;
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 3da47ccdc5e5..f9cd2561689c 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -94,14 +94,14 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
94 stats->hiwater_vm = mm->hiwater_vm * PAGE_SIZE / KB; 94 stats->hiwater_vm = mm->hiwater_vm * PAGE_SIZE / KB;
95 mmput(mm); 95 mmput(mm);
96 } 96 }
97 stats->read_char = p->rchar; 97 stats->read_char = p->ioac.chr.rchar;
98 stats->write_char = p->wchar; 98 stats->write_char = p->ioac.chr.wchar;
99 stats->read_syscalls = p->syscr; 99 stats->read_syscalls = p->ioac.chr.syscr;
100 stats->write_syscalls = p->syscw; 100 stats->write_syscalls = p->ioac.chr.syscw;
101#ifdef CONFIG_TASK_IO_ACCOUNTING 101#ifdef CONFIG_TASK_IO_ACCOUNTING
102 stats->read_bytes = p->ioac.read_bytes; 102 stats->read_bytes = p->ioac.blk.read_bytes;
103 stats->write_bytes = p->ioac.write_bytes; 103 stats->write_bytes = p->ioac.blk.write_bytes;
104 stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes; 104 stats->cancelled_write_bytes = p->ioac.blk.cancelled_write_bytes;
105#else 105#else
106 stats->read_bytes = 0; 106 stats->read_bytes = 0;
107 stats->write_bytes = 0; 107 stats->write_bytes = 0;