aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2008-07-25 04:48:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:47 -0400
commit0b6b030fc30d169bb406b34b4fc60d99dde4a9c6 (patch)
tree2bf5160ccfe22107937ddc03a1acd4fc9b1ccaf2
parent6248b1b342005a428b1247b4e89249da1528d88d (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>
-rw-r--r--include/linux/acct.h3
-rw-r--r--kernel/acct.c84
-rw-r--r--kernel/pid_namespace.c2
3 files changed, 71 insertions, 18 deletions
diff --git a/include/linux/acct.h b/include/linux/acct.h
index e8cae54e8d88..882dc7248766 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -120,17 +120,20 @@ struct acct_v3
120struct vfsmount; 120struct vfsmount;
121struct super_block; 121struct super_block;
122struct pacct_struct; 122struct pacct_struct;
123struct pid_namespace;
123extern void acct_auto_close_mnt(struct vfsmount *m); 124extern void acct_auto_close_mnt(struct vfsmount *m);
124extern void acct_auto_close(struct super_block *sb); 125extern void acct_auto_close(struct super_block *sb);
125extern void acct_init_pacct(struct pacct_struct *pacct); 126extern void acct_init_pacct(struct pacct_struct *pacct);
126extern void acct_collect(long exitcode, int group_dead); 127extern void acct_collect(long exitcode, int group_dead);
127extern void acct_process(void); 128extern void acct_process(void);
129extern void acct_exit_ns(struct pid_namespace *);
128#else 130#else
129#define acct_auto_close_mnt(x) do { } while (0) 131#define acct_auto_close_mnt(x) do { } while (0)
130#define acct_auto_close(x) do { } while (0) 132#define acct_auto_close(x) do { } while (0)
131#define acct_init_pacct(x) do { } while (0) 133#define acct_init_pacct(x) do { } while (0)
132#define acct_collect(x,y) do { } while (0) 134#define acct_collect(x,y) do { } while (0)
133#define acct_process() do { } while (0) 135#define acct_process() do { } while (0)
136#define acct_exit_ns(ns) do { } while (0)
134#endif 137#endif
135 138
136/* 139/*
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
94static DEFINE_SPINLOCK(acct_lock); 94static DEFINE_SPINLOCK(acct_lock);
95 95
96static 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 */
179static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file) 177static 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 */
290void acct_auto_close_mnt(struct vfsmount *m) 313void 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 */
305void acct_auto_close(struct super_block *sb) 334void 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
348void 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)
587void acct_process(void) 635void 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}
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 06331cc1c3f5..ea567b78d1aa 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -12,6 +12,7 @@
12#include <linux/pid_namespace.h> 12#include <linux/pid_namespace.h>
13#include <linux/syscalls.h> 13#include <linux/syscalls.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/acct.h>
15 16
16#define BITS_PER_PAGE (PAGE_SIZE*8) 17#define BITS_PER_PAGE (PAGE_SIZE*8)
17 18
@@ -181,6 +182,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
181 182
182 /* Child reaper for the pid namespace is going away */ 183 /* Child reaper for the pid namespace is going away */
183 pid_ns->child_reaper = NULL; 184 pid_ns->child_reaper = NULL;
185 acct_exit_ns(pid_ns);
184 return; 186 return;
185} 187}
186 188