diff options
-rw-r--r-- | include/linux/acct.h | 3 | ||||
-rw-r--r-- | kernel/acct.c | 84 | ||||
-rw-r--r-- | kernel/pid_namespace.c | 2 |
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 | |||
120 | struct vfsmount; | 120 | struct vfsmount; |
121 | struct super_block; | 121 | struct super_block; |
122 | struct pacct_struct; | 122 | struct pacct_struct; |
123 | struct pid_namespace; | ||
123 | extern void acct_auto_close_mnt(struct vfsmount *m); | 124 | extern void acct_auto_close_mnt(struct vfsmount *m); |
124 | extern void acct_auto_close(struct super_block *sb); | 125 | extern void acct_auto_close(struct super_block *sb); |
125 | extern void acct_init_pacct(struct pacct_struct *pacct); | 126 | extern void acct_init_pacct(struct pacct_struct *pacct); |
126 | extern void acct_collect(long exitcode, int group_dead); | 127 | extern void acct_collect(long exitcode, int group_dead); |
127 | extern void acct_process(void); | 128 | extern void acct_process(void); |
129 | extern 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 | ||
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 | } |
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 | ||