Commit 089545f0c71bab6511395c2a060d7f81a99bad58

Authored by Martin Schwidefsky
Committed by Linus Torvalds
1 parent 088c4ec16a

[PATCH] s390: cputime_t fixes

There are some more places where the use of cputime_t instead of an integer
type and the associated macros is necessary for the virtual cputime accounting
on s390.  Affected are the s390 specific appldata code and BSD process
accounting.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 16 additions and 14 deletions Inline Diff

arch/s390/appldata/appldata_os.c
1 /* 1 /*
2 * arch/s390/appldata/appldata_os.c 2 * arch/s390/appldata/appldata_os.c
3 * 3 *
4 * Data gathering module for Linux-VM Monitor Stream, Stage 1. 4 * Data gathering module for Linux-VM Monitor Stream, Stage 1.
5 * Collects misc. OS related data (CPU utilization, running processes). 5 * Collects misc. OS related data (CPU utilization, running processes).
6 * 6 *
7 * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. 7 * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH.
8 * 8 *
9 * Author: Gerald Schaefer <geraldsc@de.ibm.com> 9 * Author: Gerald Schaefer <geraldsc@de.ibm.com>
10 */ 10 */
11 11
12 #include <linux/config.h> 12 #include <linux/config.h>
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/init.h> 14 #include <linux/init.h>
15 #include <linux/slab.h> 15 #include <linux/slab.h>
16 #include <linux/errno.h> 16 #include <linux/errno.h>
17 #include <linux/kernel_stat.h> 17 #include <linux/kernel_stat.h>
18 #include <linux/netdevice.h> 18 #include <linux/netdevice.h>
19 #include <linux/sched.h> 19 #include <linux/sched.h>
20 #include <asm/smp.h> 20 #include <asm/smp.h>
21 21
22 #include "appldata.h" 22 #include "appldata.h"
23 23
24 24
25 #define MY_PRINT_NAME "appldata_os" /* for debug messages, etc. */ 25 #define MY_PRINT_NAME "appldata_os" /* for debug messages, etc. */
26 #define LOAD_INT(x) ((x) >> FSHIFT) 26 #define LOAD_INT(x) ((x) >> FSHIFT)
27 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) 27 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
28 28
29 /* 29 /*
30 * OS data 30 * OS data
31 * 31 *
32 * This is accessed as binary data by z/VM. If changes to it can't be avoided, 32 * This is accessed as binary data by z/VM. If changes to it can't be avoided,
33 * the structure version (product ID, see appldata_base.c) needs to be changed 33 * the structure version (product ID, see appldata_base.c) needs to be changed
34 * as well and all documentation and z/VM applications using it must be 34 * as well and all documentation and z/VM applications using it must be
35 * updated. 35 * updated.
36 * 36 *
37 * The record layout is documented in the Linux for zSeries Device Drivers 37 * The record layout is documented in the Linux for zSeries Device Drivers
38 * book: 38 * book:
39 * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml 39 * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
40 */ 40 */
41 struct appldata_os_per_cpu { 41 struct appldata_os_per_cpu {
42 u32 per_cpu_user; /* timer ticks spent in user mode */ 42 u32 per_cpu_user; /* timer ticks spent in user mode */
43 u32 per_cpu_nice; /* ... spent with modified priority */ 43 u32 per_cpu_nice; /* ... spent with modified priority */
44 u32 per_cpu_system; /* ... spent in kernel mode */ 44 u32 per_cpu_system; /* ... spent in kernel mode */
45 u32 per_cpu_idle; /* ... spent in idle mode */ 45 u32 per_cpu_idle; /* ... spent in idle mode */
46 46
47 // New in 2.6 --> 47 // New in 2.6 -->
48 u32 per_cpu_irq; /* ... spent in interrupts */ 48 u32 per_cpu_irq; /* ... spent in interrupts */
49 u32 per_cpu_softirq; /* ... spent in softirqs */ 49 u32 per_cpu_softirq; /* ... spent in softirqs */
50 u32 per_cpu_iowait; /* ... spent while waiting for I/O */ 50 u32 per_cpu_iowait; /* ... spent while waiting for I/O */
51 // <-- New in 2.6 51 // <-- New in 2.6
52 } __attribute__((packed)); 52 } __attribute__((packed));
53 53
54 struct appldata_os_data { 54 struct appldata_os_data {
55 u64 timestamp; 55 u64 timestamp;
56 u32 sync_count_1; /* after VM collected the record data, */ 56 u32 sync_count_1; /* after VM collected the record data, */
57 u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the 57 u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the
58 same. If not, the record has been updated on 58 same. If not, the record has been updated on
59 the Linux side while VM was collecting the 59 the Linux side while VM was collecting the
60 (possibly corrupt) data */ 60 (possibly corrupt) data */
61 61
62 u32 nr_cpus; /* number of (virtual) CPUs */ 62 u32 nr_cpus; /* number of (virtual) CPUs */
63 u32 per_cpu_size; /* size of the per-cpu data struct */ 63 u32 per_cpu_size; /* size of the per-cpu data struct */
64 u32 cpu_offset; /* offset of the first per-cpu data struct */ 64 u32 cpu_offset; /* offset of the first per-cpu data struct */
65 65
66 u32 nr_running; /* number of runnable threads */ 66 u32 nr_running; /* number of runnable threads */
67 u32 nr_threads; /* number of threads */ 67 u32 nr_threads; /* number of threads */
68 u32 avenrun[3]; /* average nr. of running processes during */ 68 u32 avenrun[3]; /* average nr. of running processes during */
69 /* the last 1, 5 and 15 minutes */ 69 /* the last 1, 5 and 15 minutes */
70 70
71 // New in 2.6 --> 71 // New in 2.6 -->
72 u32 nr_iowait; /* number of blocked threads 72 u32 nr_iowait; /* number of blocked threads
73 (waiting for I/O) */ 73 (waiting for I/O) */
74 // <-- New in 2.6 74 // <-- New in 2.6
75 75
76 /* per cpu data */ 76 /* per cpu data */
77 struct appldata_os_per_cpu os_cpu[0]; 77 struct appldata_os_per_cpu os_cpu[0];
78 } __attribute__((packed)); 78 } __attribute__((packed));
79 79
80 static struct appldata_os_data *appldata_os_data; 80 static struct appldata_os_data *appldata_os_data;
81 81
82 82
83 static inline void appldata_print_debug(struct appldata_os_data *os_data) 83 static inline void appldata_print_debug(struct appldata_os_data *os_data)
84 { 84 {
85 int a0, a1, a2, i; 85 int a0, a1, a2, i;
86 86
87 P_DEBUG("--- OS - RECORD ---\n"); 87 P_DEBUG("--- OS - RECORD ---\n");
88 P_DEBUG("nr_threads = %u\n", os_data->nr_threads); 88 P_DEBUG("nr_threads = %u\n", os_data->nr_threads);
89 P_DEBUG("nr_running = %u\n", os_data->nr_running); 89 P_DEBUG("nr_running = %u\n", os_data->nr_running);
90 P_DEBUG("nr_iowait = %u\n", os_data->nr_iowait); 90 P_DEBUG("nr_iowait = %u\n", os_data->nr_iowait);
91 P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0], 91 P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0],
92 os_data->avenrun[1], os_data->avenrun[2]); 92 os_data->avenrun[1], os_data->avenrun[2]);
93 a0 = os_data->avenrun[0]; 93 a0 = os_data->avenrun[0];
94 a1 = os_data->avenrun[1]; 94 a1 = os_data->avenrun[1];
95 a2 = os_data->avenrun[2]; 95 a2 = os_data->avenrun[2];
96 P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n", 96 P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n",
97 LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1), 97 LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1),
98 LOAD_INT(a2), LOAD_FRAC(a2)); 98 LOAD_INT(a2), LOAD_FRAC(a2));
99 99
100 P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus); 100 P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus);
101 for (i = 0; i < os_data->nr_cpus; i++) { 101 for (i = 0; i < os_data->nr_cpus; i++) {
102 P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, " 102 P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, "
103 "idle = %u, irq = %u, softirq = %u, iowait = %u\n", 103 "idle = %u, irq = %u, softirq = %u, iowait = %u\n",
104 i, 104 i,
105 os_data->os_cpu[i].per_cpu_user, 105 os_data->os_cpu[i].per_cpu_user,
106 os_data->os_cpu[i].per_cpu_nice, 106 os_data->os_cpu[i].per_cpu_nice,
107 os_data->os_cpu[i].per_cpu_system, 107 os_data->os_cpu[i].per_cpu_system,
108 os_data->os_cpu[i].per_cpu_idle, 108 os_data->os_cpu[i].per_cpu_idle,
109 os_data->os_cpu[i].per_cpu_irq, 109 os_data->os_cpu[i].per_cpu_irq,
110 os_data->os_cpu[i].per_cpu_softirq, 110 os_data->os_cpu[i].per_cpu_softirq,
111 os_data->os_cpu[i].per_cpu_iowait); 111 os_data->os_cpu[i].per_cpu_iowait);
112 } 112 }
113 113
114 P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1); 114 P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1);
115 P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2); 115 P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2);
116 P_DEBUG("timestamp = %lX\n", os_data->timestamp); 116 P_DEBUG("timestamp = %lX\n", os_data->timestamp);
117 } 117 }
118 118
119 /* 119 /*
120 * appldata_get_os_data() 120 * appldata_get_os_data()
121 * 121 *
122 * gather OS data 122 * gather OS data
123 */ 123 */
124 static void appldata_get_os_data(void *data) 124 static void appldata_get_os_data(void *data)
125 { 125 {
126 int i, j; 126 int i, j;
127 struct appldata_os_data *os_data; 127 struct appldata_os_data *os_data;
128 128
129 os_data = data; 129 os_data = data;
130 os_data->sync_count_1++; 130 os_data->sync_count_1++;
131 131
132 os_data->nr_cpus = num_online_cpus(); 132 os_data->nr_cpus = num_online_cpus();
133 133
134 os_data->nr_threads = nr_threads; 134 os_data->nr_threads = nr_threads;
135 os_data->nr_running = nr_running(); 135 os_data->nr_running = nr_running();
136 os_data->nr_iowait = nr_iowait(); 136 os_data->nr_iowait = nr_iowait();
137 os_data->avenrun[0] = avenrun[0] + (FIXED_1/200); 137 os_data->avenrun[0] = avenrun[0] + (FIXED_1/200);
138 os_data->avenrun[1] = avenrun[1] + (FIXED_1/200); 138 os_data->avenrun[1] = avenrun[1] + (FIXED_1/200);
139 os_data->avenrun[2] = avenrun[2] + (FIXED_1/200); 139 os_data->avenrun[2] = avenrun[2] + (FIXED_1/200);
140 140
141 j = 0; 141 j = 0;
142 for_each_online_cpu(i) { 142 for_each_online_cpu(i) {
143 os_data->os_cpu[j].per_cpu_user = 143 os_data->os_cpu[j].per_cpu_user =
144 kstat_cpu(i).cpustat.user; 144 cputime_to_jiffies(kstat_cpu(i).cpustat.user);
145 os_data->os_cpu[j].per_cpu_nice = 145 os_data->os_cpu[j].per_cpu_nice =
146 kstat_cpu(i).cpustat.nice; 146 cputime_to_jiffies(kstat_cpu(i).cpustat.nice);
147 os_data->os_cpu[j].per_cpu_system = 147 os_data->os_cpu[j].per_cpu_system =
148 kstat_cpu(i).cpustat.system; 148 cputime_to_jiffies(kstat_cpu(i).cpustat.system);
149 os_data->os_cpu[j].per_cpu_idle = 149 os_data->os_cpu[j].per_cpu_idle =
150 kstat_cpu(i).cpustat.idle; 150 cputime_to_jiffies(kstat_cpu(i).cpustat.idle);
151 os_data->os_cpu[j].per_cpu_irq = 151 os_data->os_cpu[j].per_cpu_irq =
152 kstat_cpu(i).cpustat.irq; 152 cputime_to_jiffies(kstat_cpu(i).cpustat.irq);
153 os_data->os_cpu[j].per_cpu_softirq = 153 os_data->os_cpu[j].per_cpu_softirq =
154 kstat_cpu(i).cpustat.softirq; 154 cputime_to_jiffies(kstat_cpu(i).cpustat.softirq);
155 os_data->os_cpu[j].per_cpu_iowait = 155 os_data->os_cpu[j].per_cpu_iowait =
156 kstat_cpu(i).cpustat.iowait; 156 cputime_to_jiffies(kstat_cpu(i).cpustat.iowait);
157 j++; 157 j++;
158 } 158 }
159 159
160 os_data->timestamp = get_clock(); 160 os_data->timestamp = get_clock();
161 os_data->sync_count_2++; 161 os_data->sync_count_2++;
162 #ifdef APPLDATA_DEBUG 162 #ifdef APPLDATA_DEBUG
163 appldata_print_debug(os_data); 163 appldata_print_debug(os_data);
164 #endif 164 #endif
165 } 165 }
166 166
167 167
168 static struct appldata_ops ops = { 168 static struct appldata_ops ops = {
169 .ctl_nr = CTL_APPLDATA_OS, 169 .ctl_nr = CTL_APPLDATA_OS,
170 .name = "os", 170 .name = "os",
171 .record_nr = APPLDATA_RECORD_OS_ID, 171 .record_nr = APPLDATA_RECORD_OS_ID,
172 .callback = &appldata_get_os_data, 172 .callback = &appldata_get_os_data,
173 .owner = THIS_MODULE, 173 .owner = THIS_MODULE,
174 }; 174 };
175 175
176 176
177 /* 177 /*
178 * appldata_os_init() 178 * appldata_os_init()
179 * 179 *
180 * init data, register ops 180 * init data, register ops
181 */ 181 */
182 static int __init appldata_os_init(void) 182 static int __init appldata_os_init(void)
183 { 183 {
184 int rc, size; 184 int rc, size;
185 185
186 size = sizeof(struct appldata_os_data) + 186 size = sizeof(struct appldata_os_data) +
187 (NR_CPUS * sizeof(struct appldata_os_per_cpu)); 187 (NR_CPUS * sizeof(struct appldata_os_per_cpu));
188 if (size > APPLDATA_MAX_REC_SIZE) { 188 if (size > APPLDATA_MAX_REC_SIZE) {
189 P_ERROR("Size of record = %i, bigger than maximum (%i)!\n", 189 P_ERROR("Size of record = %i, bigger than maximum (%i)!\n",
190 size, APPLDATA_MAX_REC_SIZE); 190 size, APPLDATA_MAX_REC_SIZE);
191 rc = -ENOMEM; 191 rc = -ENOMEM;
192 goto out; 192 goto out;
193 } 193 }
194 P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size, 194 P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size,
195 sizeof(struct appldata_os_per_cpu)); 195 sizeof(struct appldata_os_per_cpu));
196 196
197 appldata_os_data = kmalloc(size, GFP_DMA); 197 appldata_os_data = kmalloc(size, GFP_DMA);
198 if (appldata_os_data == NULL) { 198 if (appldata_os_data == NULL) {
199 P_ERROR("No memory for %s!\n", ops.name); 199 P_ERROR("No memory for %s!\n", ops.name);
200 rc = -ENOMEM; 200 rc = -ENOMEM;
201 goto out; 201 goto out;
202 } 202 }
203 memset(appldata_os_data, 0, size); 203 memset(appldata_os_data, 0, size);
204 204
205 appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu); 205 appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu);
206 appldata_os_data->cpu_offset = offsetof(struct appldata_os_data, 206 appldata_os_data->cpu_offset = offsetof(struct appldata_os_data,
207 os_cpu); 207 os_cpu);
208 P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset); 208 P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset);
209 209
210 ops.data = appldata_os_data; 210 ops.data = appldata_os_data;
211 ops.size = size; 211 ops.size = size;
212 rc = appldata_register_ops(&ops); 212 rc = appldata_register_ops(&ops);
213 if (rc != 0) { 213 if (rc != 0) {
214 P_ERROR("Error registering ops, rc = %i\n", rc); 214 P_ERROR("Error registering ops, rc = %i\n", rc);
215 kfree(appldata_os_data); 215 kfree(appldata_os_data);
216 } else { 216 } else {
217 P_DEBUG("%s-ops registered!\n", ops.name); 217 P_DEBUG("%s-ops registered!\n", ops.name);
218 } 218 }
219 out: 219 out:
220 return rc; 220 return rc;
221 } 221 }
222 222
223 /* 223 /*
224 * appldata_os_exit() 224 * appldata_os_exit()
225 * 225 *
226 * unregister ops 226 * unregister ops
227 */ 227 */
228 static void __exit appldata_os_exit(void) 228 static void __exit appldata_os_exit(void)
229 { 229 {
230 appldata_unregister_ops(&ops); 230 appldata_unregister_ops(&ops);
231 kfree(appldata_os_data); 231 kfree(appldata_os_data);
232 P_DEBUG("%s-ops unregistered!\n", ops.name); 232 P_DEBUG("%s-ops unregistered!\n", ops.name);
233 } 233 }
234 234
235 235
236 module_init(appldata_os_init); 236 module_init(appldata_os_init);
237 module_exit(appldata_os_exit); 237 module_exit(appldata_os_exit);
238 238
239 MODULE_LICENSE("GPL"); 239 MODULE_LICENSE("GPL");
240 MODULE_AUTHOR("Gerald Schaefer"); 240 MODULE_AUTHOR("Gerald Schaefer");
241 MODULE_DESCRIPTION("Linux-VM Monitor Stream, OS statistics"); 241 MODULE_DESCRIPTION("Linux-VM Monitor Stream, OS statistics");
242 242
1 /* 1 /*
2 * linux/kernel/acct.c 2 * linux/kernel/acct.c
3 * 3 *
4 * BSD Process Accounting for Linux 4 * BSD Process Accounting for Linux
5 * 5 *
6 * Author: Marco van Wieringen <mvw@planets.elm.net> 6 * Author: Marco van Wieringen <mvw@planets.elm.net>
7 * 7 *
8 * Some code based on ideas and code from: 8 * Some code based on ideas and code from:
9 * Thomas K. Dyas <tdyas@eden.rutgers.edu> 9 * Thomas K. Dyas <tdyas@eden.rutgers.edu>
10 * 10 *
11 * This file implements BSD-style process accounting. Whenever any 11 * This file implements BSD-style process accounting. Whenever any
12 * process exits, an accounting record of type "struct acct" is 12 * process exits, an accounting record of type "struct acct" is
13 * written to the file specified with the acct() system call. It is 13 * written to the file specified with the acct() system call. It is
14 * up to user-level programs to do useful things with the accounting 14 * up to user-level programs to do useful things with the accounting
15 * log. The kernel just provides the raw accounting information. 15 * log. The kernel just provides the raw accounting information.
16 * 16 *
17 * (C) Copyright 1995 - 1997 Marco van Wieringen - ELM Consultancy B.V. 17 * (C) Copyright 1995 - 1997 Marco van Wieringen - ELM Consultancy B.V.
18 * 18 *
19 * Plugged two leaks. 1) It didn't return acct_file into the free_filps if 19 * Plugged two leaks. 1) It didn't return acct_file into the free_filps if
20 * the file happened to be read-only. 2) If the accounting was suspended 20 * the file happened to be read-only. 2) If the accounting was suspended
21 * due to the lack of space it happily allowed to reopen it and completely 21 * due to the lack of space it happily allowed to reopen it and completely
22 * lost the old acct_file. 3/10/98, Al Viro. 22 * lost the old acct_file. 3/10/98, Al Viro.
23 * 23 *
24 * Now we silently close acct_file on attempt to reopen. Cleaned sys_acct(). 24 * Now we silently close acct_file on attempt to reopen. Cleaned sys_acct().
25 * XTerms and EMACS are manifestations of pure evil. 21/10/98, AV. 25 * XTerms and EMACS are manifestations of pure evil. 21/10/98, AV.
26 * 26 *
27 * Fixed a nasty interaction with with sys_umount(). If the accointing 27 * Fixed a nasty interaction with with sys_umount(). If the accointing
28 * was suspeneded we failed to stop it on umount(). Messy. 28 * was suspeneded we failed to stop it on umount(). Messy.
29 * Another one: remount to readonly didn't stop accounting. 29 * Another one: remount to readonly didn't stop accounting.
30 * Question: what should we do if we have CAP_SYS_ADMIN but not 30 * Question: what should we do if we have CAP_SYS_ADMIN but not
31 * CAP_SYS_PACCT? Current code does the following: umount returns -EBUSY 31 * CAP_SYS_PACCT? Current code does the following: umount returns -EBUSY
32 * unless we are messing with the root. In that case we are getting a 32 * unless we are messing with the root. In that case we are getting a
33 * real mess with do_remount_sb(). 9/11/98, AV. 33 * real mess with do_remount_sb(). 9/11/98, AV.
34 * 34 *
35 * Fixed a bunch of races (and pair of leaks). Probably not the best way, 35 * Fixed a bunch of races (and pair of leaks). Probably not the best way,
36 * but this one obviously doesn't introduce deadlocks. Later. BTW, found 36 * but this one obviously doesn't introduce deadlocks. Later. BTW, found
37 * one race (and leak) in BSD implementation. 37 * one race (and leak) in BSD implementation.
38 * OK, that's better. ANOTHER race and leak in BSD variant. There always 38 * OK, that's better. ANOTHER race and leak in BSD variant. There always
39 * is one more bug... 10/11/98, AV. 39 * is one more bug... 10/11/98, AV.
40 * 40 *
41 * Oh, fsck... Oopsable SMP race in do_process_acct() - we must hold 41 * Oh, fsck... Oopsable SMP race in do_process_acct() - we must hold
42 * ->mmap_sem to walk the vma list of current->mm. Nasty, since it leaks 42 * ->mmap_sem to walk the vma list of current->mm. Nasty, since it leaks
43 * a struct file opened for write. Fixed. 2/6/2000, AV. 43 * a struct file opened for write. Fixed. 2/6/2000, AV.
44 */ 44 */
45 45
46 #include <linux/config.h> 46 #include <linux/config.h>
47 #include <linux/mm.h> 47 #include <linux/mm.h>
48 #include <linux/slab.h> 48 #include <linux/slab.h>
49 #include <linux/acct.h> 49 #include <linux/acct.h>
50 #include <linux/file.h> 50 #include <linux/file.h>
51 #include <linux/tty.h> 51 #include <linux/tty.h>
52 #include <linux/security.h> 52 #include <linux/security.h>
53 #include <linux/vfs.h> 53 #include <linux/vfs.h>
54 #include <linux/jiffies.h> 54 #include <linux/jiffies.h>
55 #include <linux/times.h> 55 #include <linux/times.h>
56 #include <linux/syscalls.h> 56 #include <linux/syscalls.h>
57 #include <linux/mount.h> 57 #include <linux/mount.h>
58 #include <asm/uaccess.h> 58 #include <asm/uaccess.h>
59 #include <asm/div64.h> 59 #include <asm/div64.h>
60 #include <linux/blkdev.h> /* sector_div */ 60 #include <linux/blkdev.h> /* sector_div */
61 61
62 /* 62 /*
63 * These constants control the amount of freespace that suspend and 63 * These constants control the amount of freespace that suspend and
64 * resume the process accounting system, and the time delay between 64 * resume the process accounting system, and the time delay between
65 * each check. 65 * each check.
66 * Turned into sysctl-controllable parameters. AV, 12/11/98 66 * Turned into sysctl-controllable parameters. AV, 12/11/98
67 */ 67 */
68 68
69 int acct_parm[3] = {4, 2, 30}; 69 int acct_parm[3] = {4, 2, 30};
70 #define RESUME (acct_parm[0]) /* >foo% free space - resume */ 70 #define RESUME (acct_parm[0]) /* >foo% free space - resume */
71 #define SUSPEND (acct_parm[1]) /* <foo% free space - suspend */ 71 #define SUSPEND (acct_parm[1]) /* <foo% free space - suspend */
72 #define ACCT_TIMEOUT (acct_parm[2]) /* foo second timeout between checks */ 72 #define ACCT_TIMEOUT (acct_parm[2]) /* foo second timeout between checks */
73 73
74 /* 74 /*
75 * External references and all of the globals. 75 * External references and all of the globals.
76 */ 76 */
77 static void do_acct_process(long, struct file *); 77 static void do_acct_process(long, struct file *);
78 78
79 /* 79 /*
80 * This structure is used so that all the data protected by lock 80 * This structure is used so that all the data protected by lock
81 * can be placed in the same cache line as the lock. This primes 81 * can be placed in the same cache line as the lock. This primes
82 * the cache line to have the data after getting the lock. 82 * the cache line to have the data after getting the lock.
83 */ 83 */
84 struct acct_glbs { 84 struct acct_glbs {
85 spinlock_t lock; 85 spinlock_t lock;
86 volatile int active; 86 volatile int active;
87 volatile int needcheck; 87 volatile int needcheck;
88 struct file *file; 88 struct file *file;
89 struct timer_list timer; 89 struct timer_list timer;
90 }; 90 };
91 91
92 static struct acct_glbs acct_globals __cacheline_aligned = {SPIN_LOCK_UNLOCKED}; 92 static struct acct_glbs acct_globals __cacheline_aligned = {SPIN_LOCK_UNLOCKED};
93 93
94 /* 94 /*
95 * Called whenever the timer says to check the free space. 95 * Called whenever the timer says to check the free space.
96 */ 96 */
97 static void acct_timeout(unsigned long unused) 97 static void acct_timeout(unsigned long unused)
98 { 98 {
99 acct_globals.needcheck = 1; 99 acct_globals.needcheck = 1;
100 } 100 }
101 101
102 /* 102 /*
103 * Check the amount of free space and suspend/resume accordingly. 103 * Check the amount of free space and suspend/resume accordingly.
104 */ 104 */
105 static int check_free_space(struct file *file) 105 static int check_free_space(struct file *file)
106 { 106 {
107 struct kstatfs sbuf; 107 struct kstatfs sbuf;
108 int res; 108 int res;
109 int act; 109 int act;
110 sector_t resume; 110 sector_t resume;
111 sector_t suspend; 111 sector_t suspend;
112 112
113 spin_lock(&acct_globals.lock); 113 spin_lock(&acct_globals.lock);
114 res = acct_globals.active; 114 res = acct_globals.active;
115 if (!file || !acct_globals.needcheck) 115 if (!file || !acct_globals.needcheck)
116 goto out; 116 goto out;
117 spin_unlock(&acct_globals.lock); 117 spin_unlock(&acct_globals.lock);
118 118
119 /* May block */ 119 /* May block */
120 if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf)) 120 if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf))
121 return res; 121 return res;
122 suspend = sbuf.f_blocks * SUSPEND; 122 suspend = sbuf.f_blocks * SUSPEND;
123 resume = sbuf.f_blocks * RESUME; 123 resume = sbuf.f_blocks * RESUME;
124 124
125 sector_div(suspend, 100); 125 sector_div(suspend, 100);
126 sector_div(resume, 100); 126 sector_div(resume, 100);
127 127
128 if (sbuf.f_bavail <= suspend) 128 if (sbuf.f_bavail <= suspend)
129 act = -1; 129 act = -1;
130 else if (sbuf.f_bavail >= resume) 130 else if (sbuf.f_bavail >= resume)
131 act = 1; 131 act = 1;
132 else 132 else
133 act = 0; 133 act = 0;
134 134
135 /* 135 /*
136 * If some joker switched acct_globals.file under us we'ld better be 136 * If some joker switched acct_globals.file under us we'ld better be
137 * silent and _not_ touch anything. 137 * silent and _not_ touch anything.
138 */ 138 */
139 spin_lock(&acct_globals.lock); 139 spin_lock(&acct_globals.lock);
140 if (file != acct_globals.file) { 140 if (file != acct_globals.file) {
141 if (act) 141 if (act)
142 res = act>0; 142 res = act>0;
143 goto out; 143 goto out;
144 } 144 }
145 145
146 if (acct_globals.active) { 146 if (acct_globals.active) {
147 if (act < 0) { 147 if (act < 0) {
148 acct_globals.active = 0; 148 acct_globals.active = 0;
149 printk(KERN_INFO "Process accounting paused\n"); 149 printk(KERN_INFO "Process accounting paused\n");
150 } 150 }
151 } else { 151 } else {
152 if (act > 0) { 152 if (act > 0) {
153 acct_globals.active = 1; 153 acct_globals.active = 1;
154 printk(KERN_INFO "Process accounting resumed\n"); 154 printk(KERN_INFO "Process accounting resumed\n");
155 } 155 }
156 } 156 }
157 157
158 del_timer(&acct_globals.timer); 158 del_timer(&acct_globals.timer);
159 acct_globals.needcheck = 0; 159 acct_globals.needcheck = 0;
160 acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ; 160 acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ;
161 add_timer(&acct_globals.timer); 161 add_timer(&acct_globals.timer);
162 res = acct_globals.active; 162 res = acct_globals.active;
163 out: 163 out:
164 spin_unlock(&acct_globals.lock); 164 spin_unlock(&acct_globals.lock);
165 return res; 165 return res;
166 } 166 }
167 167
168 /* 168 /*
169 * Close the old accounting file (if currently open) and then replace 169 * Close the old accounting file (if currently open) and then replace
170 * it with file (if non-NULL). 170 * it with file (if non-NULL).
171 * 171 *
172 * NOTE: acct_globals.lock MUST be held on entry and exit. 172 * NOTE: acct_globals.lock MUST be held on entry and exit.
173 */ 173 */
174 static void acct_file_reopen(struct file *file) 174 static void acct_file_reopen(struct file *file)
175 { 175 {
176 struct file *old_acct = NULL; 176 struct file *old_acct = NULL;
177 177
178 if (acct_globals.file) { 178 if (acct_globals.file) {
179 old_acct = acct_globals.file; 179 old_acct = acct_globals.file;
180 del_timer(&acct_globals.timer); 180 del_timer(&acct_globals.timer);
181 acct_globals.active = 0; 181 acct_globals.active = 0;
182 acct_globals.needcheck = 0; 182 acct_globals.needcheck = 0;
183 acct_globals.file = NULL; 183 acct_globals.file = NULL;
184 } 184 }
185 if (file) { 185 if (file) {
186 acct_globals.file = file; 186 acct_globals.file = file;
187 acct_globals.needcheck = 0; 187 acct_globals.needcheck = 0;
188 acct_globals.active = 1; 188 acct_globals.active = 1;
189 /* It's been deleted if it was used before so this is safe */ 189 /* It's been deleted if it was used before so this is safe */
190 init_timer(&acct_globals.timer); 190 init_timer(&acct_globals.timer);
191 acct_globals.timer.function = acct_timeout; 191 acct_globals.timer.function = acct_timeout;
192 acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ; 192 acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ;
193 add_timer(&acct_globals.timer); 193 add_timer(&acct_globals.timer);
194 } 194 }
195 if (old_acct) { 195 if (old_acct) {
196 mnt_unpin(old_acct->f_vfsmnt); 196 mnt_unpin(old_acct->f_vfsmnt);
197 spin_unlock(&acct_globals.lock); 197 spin_unlock(&acct_globals.lock);
198 do_acct_process(0, old_acct); 198 do_acct_process(0, old_acct);
199 filp_close(old_acct, NULL); 199 filp_close(old_acct, NULL);
200 spin_lock(&acct_globals.lock); 200 spin_lock(&acct_globals.lock);
201 } 201 }
202 } 202 }
203 203
204 static int acct_on(char *name) 204 static int acct_on(char *name)
205 { 205 {
206 struct file *file; 206 struct file *file;
207 int error; 207 int error;
208 208
209 /* Difference from BSD - they don't do O_APPEND */ 209 /* Difference from BSD - they don't do O_APPEND */
210 file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); 210 file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
211 if (IS_ERR(file)) 211 if (IS_ERR(file))
212 return PTR_ERR(file); 212 return PTR_ERR(file);
213 213
214 if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { 214 if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
215 filp_close(file, NULL); 215 filp_close(file, NULL);
216 return -EACCES; 216 return -EACCES;
217 } 217 }
218 218
219 if (!file->f_op->write) { 219 if (!file->f_op->write) {
220 filp_close(file, NULL); 220 filp_close(file, NULL);
221 return -EIO; 221 return -EIO;
222 } 222 }
223 223
224 error = security_acct(file); 224 error = security_acct(file);
225 if (error) { 225 if (error) {
226 filp_close(file, NULL); 226 filp_close(file, NULL);
227 return error; 227 return error;
228 } 228 }
229 229
230 spin_lock(&acct_globals.lock); 230 spin_lock(&acct_globals.lock);
231 mnt_pin(file->f_vfsmnt); 231 mnt_pin(file->f_vfsmnt);
232 acct_file_reopen(file); 232 acct_file_reopen(file);
233 spin_unlock(&acct_globals.lock); 233 spin_unlock(&acct_globals.lock);
234 234
235 mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */ 235 mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */
236 236
237 return 0; 237 return 0;
238 } 238 }
239 239
240 /** 240 /**
241 * sys_acct - enable/disable process accounting 241 * sys_acct - enable/disable process accounting
242 * @name: file name for accounting records or NULL to shutdown accounting 242 * @name: file name for accounting records or NULL to shutdown accounting
243 * 243 *
244 * Returns 0 for success or negative errno values for failure. 244 * Returns 0 for success or negative errno values for failure.
245 * 245 *
246 * sys_acct() is the only system call needed to implement process 246 * sys_acct() is the only system call needed to implement process
247 * accounting. It takes the name of the file where accounting records 247 * accounting. It takes the name of the file where accounting records
248 * should be written. If the filename is NULL, accounting will be 248 * should be written. If the filename is NULL, accounting will be
249 * shutdown. 249 * shutdown.
250 */ 250 */
251 asmlinkage long sys_acct(const char __user *name) 251 asmlinkage long sys_acct(const char __user *name)
252 { 252 {
253 int error; 253 int error;
254 254
255 if (!capable(CAP_SYS_PACCT)) 255 if (!capable(CAP_SYS_PACCT))
256 return -EPERM; 256 return -EPERM;
257 257
258 if (name) { 258 if (name) {
259 char *tmp = getname(name); 259 char *tmp = getname(name);
260 if (IS_ERR(tmp)) 260 if (IS_ERR(tmp))
261 return (PTR_ERR(tmp)); 261 return (PTR_ERR(tmp));
262 error = acct_on(tmp); 262 error = acct_on(tmp);
263 putname(tmp); 263 putname(tmp);
264 } else { 264 } else {
265 error = security_acct(NULL); 265 error = security_acct(NULL);
266 if (!error) { 266 if (!error) {
267 spin_lock(&acct_globals.lock); 267 spin_lock(&acct_globals.lock);
268 acct_file_reopen(NULL); 268 acct_file_reopen(NULL);
269 spin_unlock(&acct_globals.lock); 269 spin_unlock(&acct_globals.lock);
270 } 270 }
271 } 271 }
272 return error; 272 return error;
273 } 273 }
274 274
275 /** 275 /**
276 * acct_auto_close - turn off a filesystem's accounting if it is on 276 * acct_auto_close - turn off a filesystem's accounting if it is on
277 * @m: vfsmount being shut down 277 * @m: vfsmount being shut down
278 * 278 *
279 * If the accounting is turned on for a file in the subtree pointed to 279 * If the accounting is turned on for a file in the subtree pointed to
280 * to by m, turn accounting off. Done when m is about to die. 280 * to by m, turn accounting off. Done when m is about to die.
281 */ 281 */
282 void acct_auto_close_mnt(struct vfsmount *m) 282 void acct_auto_close_mnt(struct vfsmount *m)
283 { 283 {
284 spin_lock(&acct_globals.lock); 284 spin_lock(&acct_globals.lock);
285 if (acct_globals.file && acct_globals.file->f_vfsmnt == m) 285 if (acct_globals.file && acct_globals.file->f_vfsmnt == m)
286 acct_file_reopen(NULL); 286 acct_file_reopen(NULL);
287 spin_unlock(&acct_globals.lock); 287 spin_unlock(&acct_globals.lock);
288 } 288 }
289 289
290 /** 290 /**
291 * acct_auto_close - turn off a filesystem's accounting if it is on 291 * acct_auto_close - turn off a filesystem's accounting if it is on
292 * @sb: super block for the filesystem 292 * @sb: super block for the filesystem
293 * 293 *
294 * If the accounting is turned on for a file in the filesystem pointed 294 * If the accounting is turned on for a file in the filesystem pointed
295 * to by sb, turn accounting off. 295 * to by sb, turn accounting off.
296 */ 296 */
297 void acct_auto_close(struct super_block *sb) 297 void acct_auto_close(struct super_block *sb)
298 { 298 {
299 spin_lock(&acct_globals.lock); 299 spin_lock(&acct_globals.lock);
300 if (acct_globals.file && 300 if (acct_globals.file &&
301 acct_globals.file->f_vfsmnt->mnt_sb == sb) { 301 acct_globals.file->f_vfsmnt->mnt_sb == sb) {
302 acct_file_reopen(NULL); 302 acct_file_reopen(NULL);
303 } 303 }
304 spin_unlock(&acct_globals.lock); 304 spin_unlock(&acct_globals.lock);
305 } 305 }
306 306
307 /* 307 /*
308 * encode an unsigned long into a comp_t 308 * encode an unsigned long into a comp_t
309 * 309 *
310 * This routine has been adopted from the encode_comp_t() function in 310 * This routine has been adopted from the encode_comp_t() function in
311 * the kern_acct.c file of the FreeBSD operating system. The encoding 311 * the kern_acct.c file of the FreeBSD operating system. The encoding
312 * is a 13-bit fraction with a 3-bit (base 8) exponent. 312 * is a 13-bit fraction with a 3-bit (base 8) exponent.
313 */ 313 */
314 314
315 #define MANTSIZE 13 /* 13 bit mantissa. */ 315 #define MANTSIZE 13 /* 13 bit mantissa. */
316 #define EXPSIZE 3 /* Base 8 (3 bit) exponent. */ 316 #define EXPSIZE 3 /* Base 8 (3 bit) exponent. */
317 #define MAXFRACT ((1 << MANTSIZE) - 1) /* Maximum fractional value. */ 317 #define MAXFRACT ((1 << MANTSIZE) - 1) /* Maximum fractional value. */
318 318
319 static comp_t encode_comp_t(unsigned long value) 319 static comp_t encode_comp_t(unsigned long value)
320 { 320 {
321 int exp, rnd; 321 int exp, rnd;
322 322
323 exp = rnd = 0; 323 exp = rnd = 0;
324 while (value > MAXFRACT) { 324 while (value > MAXFRACT) {
325 rnd = value & (1 << (EXPSIZE - 1)); /* Round up? */ 325 rnd = value & (1 << (EXPSIZE - 1)); /* Round up? */
326 value >>= EXPSIZE; /* Base 8 exponent == 3 bit shift. */ 326 value >>= EXPSIZE; /* Base 8 exponent == 3 bit shift. */
327 exp++; 327 exp++;
328 } 328 }
329 329
330 /* 330 /*
331 * If we need to round up, do it (and handle overflow correctly). 331 * If we need to round up, do it (and handle overflow correctly).
332 */ 332 */
333 if (rnd && (++value > MAXFRACT)) { 333 if (rnd && (++value > MAXFRACT)) {
334 value >>= EXPSIZE; 334 value >>= EXPSIZE;
335 exp++; 335 exp++;
336 } 336 }
337 337
338 /* 338 /*
339 * Clean it up and polish it off. 339 * Clean it up and polish it off.
340 */ 340 */
341 exp <<= MANTSIZE; /* Shift the exponent into place */ 341 exp <<= MANTSIZE; /* Shift the exponent into place */
342 exp += value; /* and add on the mantissa. */ 342 exp += value; /* and add on the mantissa. */
343 return exp; 343 return exp;
344 } 344 }
345 345
346 #if ACCT_VERSION==1 || ACCT_VERSION==2 346 #if ACCT_VERSION==1 || ACCT_VERSION==2
347 /* 347 /*
348 * encode an u64 into a comp2_t (24 bits) 348 * encode an u64 into a comp2_t (24 bits)
349 * 349 *
350 * Format: 5 bit base 2 exponent, 20 bits mantissa. 350 * Format: 5 bit base 2 exponent, 20 bits mantissa.
351 * The leading bit of the mantissa is not stored, but implied for 351 * The leading bit of the mantissa is not stored, but implied for
352 * non-zero exponents. 352 * non-zero exponents.
353 * Largest encodable value is 50 bits. 353 * Largest encodable value is 50 bits.
354 */ 354 */
355 355
356 #define MANTSIZE2 20 /* 20 bit mantissa. */ 356 #define MANTSIZE2 20 /* 20 bit mantissa. */
357 #define EXPSIZE2 5 /* 5 bit base 2 exponent. */ 357 #define EXPSIZE2 5 /* 5 bit base 2 exponent. */
358 #define MAXFRACT2 ((1ul << MANTSIZE2) - 1) /* Maximum fractional value. */ 358 #define MAXFRACT2 ((1ul << MANTSIZE2) - 1) /* Maximum fractional value. */
359 #define MAXEXP2 ((1 <<EXPSIZE2) - 1) /* Maximum exponent. */ 359 #define MAXEXP2 ((1 <<EXPSIZE2) - 1) /* Maximum exponent. */
360 360
361 static comp2_t encode_comp2_t(u64 value) 361 static comp2_t encode_comp2_t(u64 value)
362 { 362 {
363 int exp, rnd; 363 int exp, rnd;
364 364
365 exp = (value > (MAXFRACT2>>1)); 365 exp = (value > (MAXFRACT2>>1));
366 rnd = 0; 366 rnd = 0;
367 while (value > MAXFRACT2) { 367 while (value > MAXFRACT2) {
368 rnd = value & 1; 368 rnd = value & 1;
369 value >>= 1; 369 value >>= 1;
370 exp++; 370 exp++;
371 } 371 }
372 372
373 /* 373 /*
374 * If we need to round up, do it (and handle overflow correctly). 374 * If we need to round up, do it (and handle overflow correctly).
375 */ 375 */
376 if (rnd && (++value > MAXFRACT2)) { 376 if (rnd && (++value > MAXFRACT2)) {
377 value >>= 1; 377 value >>= 1;
378 exp++; 378 exp++;
379 } 379 }
380 380
381 if (exp > MAXEXP2) { 381 if (exp > MAXEXP2) {
382 /* Overflow. Return largest representable number instead. */ 382 /* Overflow. Return largest representable number instead. */
383 return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1; 383 return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1;
384 } else { 384 } else {
385 return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1)); 385 return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
386 } 386 }
387 } 387 }
388 #endif 388 #endif
389 389
390 #if ACCT_VERSION==3 390 #if ACCT_VERSION==3
391 /* 391 /*
392 * encode an u64 into a 32 bit IEEE float 392 * encode an u64 into a 32 bit IEEE float
393 */ 393 */
394 static u32 encode_float(u64 value) 394 static u32 encode_float(u64 value)
395 { 395 {
396 unsigned exp = 190; 396 unsigned exp = 190;
397 unsigned u; 397 unsigned u;
398 398
399 if (value==0) return 0; 399 if (value==0) return 0;
400 while ((s64)value > 0){ 400 while ((s64)value > 0){
401 value <<= 1; 401 value <<= 1;
402 exp--; 402 exp--;
403 } 403 }
404 u = (u32)(value >> 40) & 0x7fffffu; 404 u = (u32)(value >> 40) & 0x7fffffu;
405 return u | (exp << 23); 405 return u | (exp << 23);
406 } 406 }
407 #endif 407 #endif
408 408
409 /* 409 /*
410 * Write an accounting entry for an exiting process 410 * Write an accounting entry for an exiting process
411 * 411 *
412 * The acct_process() call is the workhorse of the process 412 * The acct_process() call is the workhorse of the process
413 * accounting system. The struct acct is built here and then written 413 * accounting system. The struct acct is built here and then written
414 * into the accounting file. This function should only be called from 414 * into the accounting file. This function should only be called from
415 * do_exit(). 415 * do_exit().
416 */ 416 */
417 417
418 /* 418 /*
419 * do_acct_process does all actual work. Caller holds the reference to file. 419 * do_acct_process does all actual work. Caller holds the reference to file.
420 */ 420 */
421 static void do_acct_process(long exitcode, struct file *file) 421 static void do_acct_process(long exitcode, struct file *file)
422 { 422 {
423 acct_t ac; 423 acct_t ac;
424 mm_segment_t fs; 424 mm_segment_t fs;
425 unsigned long vsize; 425 unsigned long vsize;
426 unsigned long flim; 426 unsigned long flim;
427 u64 elapsed; 427 u64 elapsed;
428 u64 run_time; 428 u64 run_time;
429 struct timespec uptime; 429 struct timespec uptime;
430 unsigned long jiffies;
430 431
431 /* 432 /*
432 * First check to see if there is enough free_space to continue 433 * First check to see if there is enough free_space to continue
433 * the process accounting system. 434 * the process accounting system.
434 */ 435 */
435 if (!check_free_space(file)) 436 if (!check_free_space(file))
436 return; 437 return;
437 438
438 /* 439 /*
439 * Fill the accounting struct with the needed info as recorded 440 * Fill the accounting struct with the needed info as recorded
440 * by the different kernel functions. 441 * by the different kernel functions.
441 */ 442 */
442 memset((caddr_t)&ac, 0, sizeof(acct_t)); 443 memset((caddr_t)&ac, 0, sizeof(acct_t));
443 444
444 ac.ac_version = ACCT_VERSION | ACCT_BYTEORDER; 445 ac.ac_version = ACCT_VERSION | ACCT_BYTEORDER;
445 strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm)); 446 strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm));
446 447
447 /* calculate run_time in nsec*/ 448 /* calculate run_time in nsec*/
448 do_posix_clock_monotonic_gettime(&uptime); 449 do_posix_clock_monotonic_gettime(&uptime);
449 run_time = (u64)uptime.tv_sec*NSEC_PER_SEC + uptime.tv_nsec; 450 run_time = (u64)uptime.tv_sec*NSEC_PER_SEC + uptime.tv_nsec;
450 run_time -= (u64)current->start_time.tv_sec*NSEC_PER_SEC 451 run_time -= (u64)current->start_time.tv_sec*NSEC_PER_SEC
451 + current->start_time.tv_nsec; 452 + current->start_time.tv_nsec;
452 /* convert nsec -> AHZ */ 453 /* convert nsec -> AHZ */
453 elapsed = nsec_to_AHZ(run_time); 454 elapsed = nsec_to_AHZ(run_time);
454 #if ACCT_VERSION==3 455 #if ACCT_VERSION==3
455 ac.ac_etime = encode_float(elapsed); 456 ac.ac_etime = encode_float(elapsed);
456 #else 457 #else
457 ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ? 458 ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ?
458 (unsigned long) elapsed : (unsigned long) -1l); 459 (unsigned long) elapsed : (unsigned long) -1l);
459 #endif 460 #endif
460 #if ACCT_VERSION==1 || ACCT_VERSION==2 461 #if ACCT_VERSION==1 || ACCT_VERSION==2
461 { 462 {
462 /* new enlarged etime field */ 463 /* new enlarged etime field */
463 comp2_t etime = encode_comp2_t(elapsed); 464 comp2_t etime = encode_comp2_t(elapsed);
464 ac.ac_etime_hi = etime >> 16; 465 ac.ac_etime_hi = etime >> 16;
465 ac.ac_etime_lo = (u16) etime; 466 ac.ac_etime_lo = (u16) etime;
466 } 467 }
467 #endif 468 #endif
468 do_div(elapsed, AHZ); 469 do_div(elapsed, AHZ);
469 ac.ac_btime = xtime.tv_sec - elapsed; 470 ac.ac_btime = xtime.tv_sec - elapsed;
470 ac.ac_utime = encode_comp_t(jiffies_to_AHZ( 471 jiffies = cputime_to_jiffies(cputime_add(current->group_leader->utime,
471 current->signal->utime + 472 current->signal->utime));
472 current->group_leader->utime)); 473 ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies));
473 ac.ac_stime = encode_comp_t(jiffies_to_AHZ( 474 jiffies = cputime_to_jiffies(cputime_add(current->group_leader->stime,
474 current->signal->stime + 475 current->signal->stime));
475 current->group_leader->stime)); 476 ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies));
476 /* we really need to bite the bullet and change layout */ 477 /* we really need to bite the bullet and change layout */
477 ac.ac_uid = current->uid; 478 ac.ac_uid = current->uid;
478 ac.ac_gid = current->gid; 479 ac.ac_gid = current->gid;
479 #if ACCT_VERSION==2 480 #if ACCT_VERSION==2
480 ac.ac_ahz = AHZ; 481 ac.ac_ahz = AHZ;
481 #endif 482 #endif
482 #if ACCT_VERSION==1 || ACCT_VERSION==2 483 #if ACCT_VERSION==1 || ACCT_VERSION==2
483 /* backward-compatible 16 bit fields */ 484 /* backward-compatible 16 bit fields */
484 ac.ac_uid16 = current->uid; 485 ac.ac_uid16 = current->uid;
485 ac.ac_gid16 = current->gid; 486 ac.ac_gid16 = current->gid;
486 #endif 487 #endif
487 #if ACCT_VERSION==3 488 #if ACCT_VERSION==3
488 ac.ac_pid = current->tgid; 489 ac.ac_pid = current->tgid;
489 ac.ac_ppid = current->parent->tgid; 490 ac.ac_ppid = current->parent->tgid;
490 #endif 491 #endif
491 492
492 read_lock(&tasklist_lock); /* pin current->signal */ 493 read_lock(&tasklist_lock); /* pin current->signal */
493 ac.ac_tty = current->signal->tty ? 494 ac.ac_tty = current->signal->tty ?
494 old_encode_dev(tty_devnum(current->signal->tty)) : 0; 495 old_encode_dev(tty_devnum(current->signal->tty)) : 0;
495 read_unlock(&tasklist_lock); 496 read_unlock(&tasklist_lock);
496 497
497 ac.ac_flag = 0; 498 ac.ac_flag = 0;
498 if (current->flags & PF_FORKNOEXEC) 499 if (current->flags & PF_FORKNOEXEC)
499 ac.ac_flag |= AFORK; 500 ac.ac_flag |= AFORK;
500 if (current->flags & PF_SUPERPRIV) 501 if (current->flags & PF_SUPERPRIV)
501 ac.ac_flag |= ASU; 502 ac.ac_flag |= ASU;
502 if (current->flags & PF_DUMPCORE) 503 if (current->flags & PF_DUMPCORE)
503 ac.ac_flag |= ACORE; 504 ac.ac_flag |= ACORE;
504 if (current->flags & PF_SIGNALED) 505 if (current->flags & PF_SIGNALED)
505 ac.ac_flag |= AXSIG; 506 ac.ac_flag |= AXSIG;
506 507
507 vsize = 0; 508 vsize = 0;
508 if (current->mm) { 509 if (current->mm) {
509 struct vm_area_struct *vma; 510 struct vm_area_struct *vma;
510 down_read(&current->mm->mmap_sem); 511 down_read(&current->mm->mmap_sem);
511 vma = current->mm->mmap; 512 vma = current->mm->mmap;
512 while (vma) { 513 while (vma) {
513 vsize += vma->vm_end - vma->vm_start; 514 vsize += vma->vm_end - vma->vm_start;
514 vma = vma->vm_next; 515 vma = vma->vm_next;
515 } 516 }
516 up_read(&current->mm->mmap_sem); 517 up_read(&current->mm->mmap_sem);
517 } 518 }
518 vsize = vsize / 1024; 519 vsize = vsize / 1024;
519 ac.ac_mem = encode_comp_t(vsize); 520 ac.ac_mem = encode_comp_t(vsize);
520 ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ 521 ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
521 ac.ac_rw = encode_comp_t(ac.ac_io / 1024); 522 ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
522 ac.ac_minflt = encode_comp_t(current->signal->min_flt + 523 ac.ac_minflt = encode_comp_t(current->signal->min_flt +
523 current->group_leader->min_flt); 524 current->group_leader->min_flt);
524 ac.ac_majflt = encode_comp_t(current->signal->maj_flt + 525 ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
525 current->group_leader->maj_flt); 526 current->group_leader->maj_flt);
526 ac.ac_swaps = encode_comp_t(0); 527 ac.ac_swaps = encode_comp_t(0);
527 ac.ac_exitcode = exitcode; 528 ac.ac_exitcode = exitcode;
528 529
529 /* 530 /*
530 * Kernel segment override to datasegment and write it 531 * Kernel segment override to datasegment and write it
531 * to the accounting file. 532 * to the accounting file.
532 */ 533 */
533 fs = get_fs(); 534 fs = get_fs();
534 set_fs(KERNEL_DS); 535 set_fs(KERNEL_DS);
535 /* 536 /*
536 * Accounting records are not subject to resource limits. 537 * Accounting records are not subject to resource limits.
537 */ 538 */
538 flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; 539 flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
539 current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 540 current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
540 file->f_op->write(file, (char *)&ac, 541 file->f_op->write(file, (char *)&ac,
541 sizeof(acct_t), &file->f_pos); 542 sizeof(acct_t), &file->f_pos);
542 current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim; 543 current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
543 set_fs(fs); 544 set_fs(fs);
544 } 545 }
545 546
546 /** 547 /**
547 * acct_process - now just a wrapper around do_acct_process 548 * acct_process - now just a wrapper around do_acct_process
548 * @exitcode: task exit code 549 * @exitcode: task exit code
549 * 550 *
550 * handles process accounting for an exiting task 551 * handles process accounting for an exiting task
551 */ 552 */
552 void acct_process(long exitcode) 553 void acct_process(long exitcode)
553 { 554 {
554 struct file *file = NULL; 555 struct file *file = NULL;
555 556
556 /* 557 /*
557 * accelerate the common fastpath: 558 * accelerate the common fastpath:
558 */ 559 */
559 if (!acct_globals.file) 560 if (!acct_globals.file)
560 return; 561 return;
561 562
562 spin_lock(&acct_globals.lock); 563 spin_lock(&acct_globals.lock);
563 file = acct_globals.file; 564 file = acct_globals.file;
564 if (unlikely(!file)) { 565 if (unlikely(!file)) {
565 spin_unlock(&acct_globals.lock); 566 spin_unlock(&acct_globals.lock);
566 return; 567 return;
567 } 568 }
568 get_file(file); 569 get_file(file);
569 spin_unlock(&acct_globals.lock); 570 spin_unlock(&acct_globals.lock);
570 571
571 do_acct_process(exitcode, file); 572 do_acct_process(exitcode, file);
572 fput(file); 573 fput(file);
573 } 574 }
574 575
575 576
576 /** 577 /**
577 * acct_update_integrals - update mm integral fields in task_struct 578 * acct_update_integrals - update mm integral fields in task_struct
578 * @tsk: task_struct for accounting 579 * @tsk: task_struct for accounting
579 */ 580 */
580 void acct_update_integrals(struct task_struct *tsk) 581 void acct_update_integrals(struct task_struct *tsk)
581 { 582 {
582 if (likely(tsk->mm)) { 583 if (likely(tsk->mm)) {
583 long delta = tsk->stime - tsk->acct_stimexpd; 584 long delta =
585 cputime_to_jiffies(tsk->stime) - tsk->acct_stimexpd;
584 586
585 if (delta == 0) 587 if (delta == 0)
586 return; 588 return;
587 tsk->acct_stimexpd = tsk->stime; 589 tsk->acct_stimexpd = tsk->stime;
588 tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm); 590 tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
589 tsk->acct_vm_mem1 += delta * tsk->mm->total_vm; 591 tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
590 } 592 }
591 } 593 }
592 594
593 /** 595 /**
594 * acct_clear_integrals - clear the mm integral fields in task_struct 596 * acct_clear_integrals - clear the mm integral fields in task_struct
595 * @tsk: task_struct whose accounting fields are cleared 597 * @tsk: task_struct whose accounting fields are cleared
596 */ 598 */
597 void acct_clear_integrals(struct task_struct *tsk) 599 void acct_clear_integrals(struct task_struct *tsk)
598 { 600 {
599 if (tsk) { 601 if (tsk) {
600 tsk->acct_stimexpd = 0; 602 tsk->acct_stimexpd = 0;
601 tsk->acct_rss_mem1 = 0; 603 tsk->acct_rss_mem1 = 0;
602 tsk->acct_vm_mem1 = 0; 604 tsk->acct_vm_mem1 = 0;
603 } 605 }
604 } 606 }
605 607