diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-07-25 04:48:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:47 -0400 |
commit | 0b6b030fc30d169bb406b34b4fc60d99dde4a9c6 (patch) | |
tree | 2bf5160ccfe22107937ddc03a1acd4fc9b1ccaf2 /kernel/acct.c | |
parent | 6248b1b342005a428b1247b4e89249da1528d88d (diff) |
bsdacct: switch from global bsd_acct_struct instance to per-pidns one
Allocate the structure on the first call to sys_acct(). After this each
namespace, that ordered the accounting, will live with this structure till
its own death.
Two notes
- routines, that close the accounting on fs umount time use
the init_pid_ns's acct by now;
- accounting routine accounts to dying task's namespace
(also by now).
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/acct.c')
-rw-r--r-- | kernel/acct.c | 84 |
1 files changed, 66 insertions, 18 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index 72d4760c8da8..febbbc67157e 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -93,8 +93,6 @@ struct bsd_acct_struct { | |||
93 | 93 | ||
94 | static DEFINE_SPINLOCK(acct_lock); | 94 | static DEFINE_SPINLOCK(acct_lock); |
95 | 95 | ||
96 | static struct bsd_acct_struct acct_globals __cacheline_aligned; | ||
97 | |||
98 | /* | 96 | /* |
99 | * Called whenever the timer says to check the free space. | 97 | * Called whenever the timer says to check the free space. |
100 | */ | 98 | */ |
@@ -176,7 +174,8 @@ out: | |||
176 | * | 174 | * |
177 | * NOTE: acct_lock MUST be held on entry and exit. | 175 | * NOTE: acct_lock MUST be held on entry and exit. |
178 | */ | 176 | */ |
179 | static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file) | 177 | static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, |
178 | struct pid_namespace *ns) | ||
180 | { | 179 | { |
181 | struct file *old_acct = NULL; | 180 | struct file *old_acct = NULL; |
182 | struct pid_namespace *old_ns = NULL; | 181 | struct pid_namespace *old_ns = NULL; |
@@ -188,10 +187,11 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file) | |||
188 | acct->active = 0; | 187 | acct->active = 0; |
189 | acct->needcheck = 0; | 188 | acct->needcheck = 0; |
190 | acct->file = NULL; | 189 | acct->file = NULL; |
190 | acct->ns = NULL; | ||
191 | } | 191 | } |
192 | if (file) { | 192 | if (file) { |
193 | acct->file = file; | 193 | acct->file = file; |
194 | acct->ns = get_pid_ns(task_active_pid_ns(current)); | 194 | acct->ns = ns; |
195 | acct->needcheck = 0; | 195 | acct->needcheck = 0; |
196 | acct->active = 1; | 196 | acct->active = 1; |
197 | /* It's been deleted if it was used before so this is safe */ | 197 | /* It's been deleted if it was used before so this is safe */ |
@@ -204,7 +204,6 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file) | |||
204 | spin_unlock(&acct_lock); | 204 | spin_unlock(&acct_lock); |
205 | do_acct_process(acct, old_ns, old_acct); | 205 | do_acct_process(acct, old_ns, old_acct); |
206 | filp_close(old_acct, NULL); | 206 | filp_close(old_acct, NULL); |
207 | put_pid_ns(old_ns); | ||
208 | spin_lock(&acct_lock); | 207 | spin_lock(&acct_lock); |
209 | } | 208 | } |
210 | } | 209 | } |
@@ -213,6 +212,8 @@ static int acct_on(char *name) | |||
213 | { | 212 | { |
214 | struct file *file; | 213 | struct file *file; |
215 | int error; | 214 | int error; |
215 | struct pid_namespace *ns; | ||
216 | struct bsd_acct_struct *acct = NULL; | ||
216 | 217 | ||
217 | /* Difference from BSD - they don't do O_APPEND */ | 218 | /* Difference from BSD - they don't do O_APPEND */ |
218 | file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); | 219 | file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); |
@@ -229,18 +230,34 @@ static int acct_on(char *name) | |||
229 | return -EIO; | 230 | return -EIO; |
230 | } | 231 | } |
231 | 232 | ||
233 | ns = task_active_pid_ns(current); | ||
234 | if (ns->bacct == NULL) { | ||
235 | acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); | ||
236 | if (acct == NULL) { | ||
237 | filp_close(file, NULL); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | } | ||
241 | |||
232 | error = security_acct(file); | 242 | error = security_acct(file); |
233 | if (error) { | 243 | if (error) { |
244 | kfree(acct); | ||
234 | filp_close(file, NULL); | 245 | filp_close(file, NULL); |
235 | return error; | 246 | return error; |
236 | } | 247 | } |
237 | 248 | ||
238 | spin_lock(&acct_lock); | 249 | spin_lock(&acct_lock); |
250 | if (ns->bacct == NULL) { | ||
251 | ns->bacct = acct; | ||
252 | acct = NULL; | ||
253 | } | ||
254 | |||
239 | mnt_pin(file->f_path.mnt); | 255 | mnt_pin(file->f_path.mnt); |
240 | acct_file_reopen(&acct_globals, file); | 256 | acct_file_reopen(ns->bacct, file, ns); |
241 | spin_unlock(&acct_lock); | 257 | spin_unlock(&acct_lock); |
242 | 258 | ||
243 | mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ | 259 | mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ |
260 | kfree(acct); | ||
244 | 261 | ||
245 | return 0; | 262 | return 0; |
246 | } | 263 | } |
@@ -270,10 +287,16 @@ asmlinkage long sys_acct(const char __user *name) | |||
270 | error = acct_on(tmp); | 287 | error = acct_on(tmp); |
271 | putname(tmp); | 288 | putname(tmp); |
272 | } else { | 289 | } else { |
290 | struct bsd_acct_struct *acct; | ||
291 | |||
292 | acct = task_active_pid_ns(current)->bacct; | ||
293 | if (acct == NULL) | ||
294 | return 0; | ||
295 | |||
273 | error = security_acct(NULL); | 296 | error = security_acct(NULL); |
274 | if (!error) { | 297 | if (!error) { |
275 | spin_lock(&acct_lock); | 298 | spin_lock(&acct_lock); |
276 | acct_file_reopen(&acct_globals, NULL); | 299 | acct_file_reopen(acct, NULL, NULL); |
277 | spin_unlock(&acct_lock); | 300 | spin_unlock(&acct_lock); |
278 | } | 301 | } |
279 | } | 302 | } |
@@ -289,9 +312,15 @@ asmlinkage long sys_acct(const char __user *name) | |||
289 | */ | 312 | */ |
290 | void acct_auto_close_mnt(struct vfsmount *m) | 313 | void acct_auto_close_mnt(struct vfsmount *m) |
291 | { | 314 | { |
315 | struct bsd_acct_struct *acct; | ||
316 | |||
317 | acct = init_pid_ns.bacct; | ||
318 | if (acct == NULL) | ||
319 | return; | ||
320 | |||
292 | spin_lock(&acct_lock); | 321 | spin_lock(&acct_lock); |
293 | if (acct_globals.file && acct_globals.file->f_path.mnt == m) | 322 | if (acct->file && acct->file->f_path.mnt == m) |
294 | acct_file_reopen(&acct_globals, NULL); | 323 | acct_file_reopen(acct, NULL, NULL); |
295 | spin_unlock(&acct_lock); | 324 | spin_unlock(&acct_lock); |
296 | } | 325 | } |
297 | 326 | ||
@@ -304,10 +333,29 @@ void acct_auto_close_mnt(struct vfsmount *m) | |||
304 | */ | 333 | */ |
305 | void acct_auto_close(struct super_block *sb) | 334 | void acct_auto_close(struct super_block *sb) |
306 | { | 335 | { |
336 | struct bsd_acct_struct *acct; | ||
337 | |||
338 | acct = init_pid_ns.bacct; | ||
339 | if (acct == NULL) | ||
340 | return; | ||
341 | |||
307 | spin_lock(&acct_lock); | 342 | spin_lock(&acct_lock); |
308 | if (acct_globals.file && | 343 | if (acct->file && acct->file->f_path.mnt->mnt_sb == sb) |
309 | acct_globals.file->f_path.mnt->mnt_sb == sb) { | 344 | acct_file_reopen(acct, NULL, NULL); |
310 | acct_file_reopen(&acct_globals, NULL); | 345 | spin_unlock(&acct_lock); |
346 | } | ||
347 | |||
348 | void acct_exit_ns(struct pid_namespace *ns) | ||
349 | { | ||
350 | struct bsd_acct_struct *acct; | ||
351 | |||
352 | spin_lock(&acct_lock); | ||
353 | acct = ns->bacct; | ||
354 | if (acct != NULL) { | ||
355 | if (acct->file != NULL) | ||
356 | acct_file_reopen(acct, NULL, NULL); | ||
357 | |||
358 | kfree(acct); | ||
311 | } | 359 | } |
312 | spin_unlock(&acct_lock); | 360 | spin_unlock(&acct_lock); |
313 | } | 361 | } |
@@ -587,25 +635,25 @@ void acct_collect(long exitcode, int group_dead) | |||
587 | void acct_process(void) | 635 | void acct_process(void) |
588 | { | 636 | { |
589 | struct file *file = NULL; | 637 | struct file *file = NULL; |
590 | struct pid_namespace *ns; | 638 | struct pid_namespace *ns = task_active_pid_ns(current); |
639 | struct bsd_acct_struct *acct; | ||
591 | 640 | ||
641 | acct = ns->bacct; | ||
592 | /* | 642 | /* |
593 | * accelerate the common fastpath: | 643 | * accelerate the common fastpath: |
594 | */ | 644 | */ |
595 | if (!acct_globals.file) | 645 | if (!acct || !acct->file) |
596 | return; | 646 | return; |
597 | 647 | ||
598 | spin_lock(&acct_lock); | 648 | spin_lock(&acct_lock); |
599 | file = acct_globals.file; | 649 | file = acct->file; |
600 | if (unlikely(!file)) { | 650 | if (unlikely(!file)) { |
601 | spin_unlock(&acct_lock); | 651 | spin_unlock(&acct_lock); |
602 | return; | 652 | return; |
603 | } | 653 | } |
604 | get_file(file); | 654 | get_file(file); |
605 | ns = get_pid_ns(acct_globals.ns); | ||
606 | spin_unlock(&acct_lock); | 655 | spin_unlock(&acct_lock); |
607 | 656 | ||
608 | do_acct_process(&acct_globals, ns, file); | 657 | do_acct_process(acct, ns, file); |
609 | fput(file); | 658 | fput(file); |
610 | put_pid_ns(ns); | ||
611 | } | 659 | } |