Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Pavel Emelyanov and committed by
Linus Torvalds
0b6b030f 6248b1b3

+71 -18
+3
include/linux/acct.h
··· 120 120 struct vfsmount; 121 121 struct super_block; 122 122 struct pacct_struct; 123 + struct pid_namespace; 123 124 extern void acct_auto_close_mnt(struct vfsmount *m); 124 125 extern void acct_auto_close(struct super_block *sb); 125 126 extern void acct_init_pacct(struct pacct_struct *pacct); 126 127 extern void acct_collect(long exitcode, int group_dead); 127 128 extern void acct_process(void); 129 + extern void acct_exit_ns(struct pid_namespace *); 128 130 #else 129 131 #define acct_auto_close_mnt(x) do { } while (0) 130 132 #define acct_auto_close(x) do { } while (0) 131 133 #define acct_init_pacct(x) do { } while (0) 132 134 #define acct_collect(x,y) do { } while (0) 133 135 #define acct_process() do { } while (0) 136 + #define acct_exit_ns(ns) do { } while (0) 134 137 #endif 135 138 136 139 /*
+66 -18
kernel/acct.c
··· 93 93 94 94 static DEFINE_SPINLOCK(acct_lock); 95 95 96 - static struct bsd_acct_struct acct_globals __cacheline_aligned; 97 - 98 96 /* 99 97 * Called whenever the timer says to check the free space. 100 98 */ ··· 174 176 * 175 177 * NOTE: acct_lock MUST be held on entry and exit. 176 178 */ 177 - static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file) 179 + static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, 180 + struct pid_namespace *ns) 178 181 { 179 182 struct file *old_acct = NULL; 180 183 struct pid_namespace *old_ns = NULL; ··· 187 188 acct->active = 0; 188 189 acct->needcheck = 0; 189 190 acct->file = NULL; 191 + acct->ns = NULL; 190 192 } 191 193 if (file) { 192 194 acct->file = file; 193 - acct->ns = get_pid_ns(task_active_pid_ns(current)); 195 + acct->ns = ns; 194 196 acct->needcheck = 0; 195 197 acct->active = 1; 196 198 /* It's been deleted if it was used before so this is safe */ ··· 204 204 spin_unlock(&acct_lock); 205 205 do_acct_process(acct, old_ns, old_acct); 206 206 filp_close(old_acct, NULL); 207 - put_pid_ns(old_ns); 208 207 spin_lock(&acct_lock); 209 208 } 210 209 } ··· 212 213 { 213 214 struct file *file; 214 215 int error; 216 + struct pid_namespace *ns; 217 + struct bsd_acct_struct *acct = NULL; 215 218 216 219 /* Difference from BSD - they don't do O_APPEND */ 217 220 file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); ··· 230 229 return -EIO; 231 230 } 232 231 232 + ns = task_active_pid_ns(current); 233 + if (ns->bacct == NULL) { 234 + acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); 235 + if (acct == NULL) { 236 + filp_close(file, NULL); 237 + return -ENOMEM; 238 + } 239 + } 240 + 233 241 error = security_acct(file); 234 242 if (error) { 243 + kfree(acct); 235 244 filp_close(file, NULL); 236 245 return error; 237 246 } 238 247 239 248 spin_lock(&acct_lock); 249 + if (ns->bacct == NULL) { 250 + ns->bacct = acct; 251 + acct = NULL; 252 + } 253 + 240 254 mnt_pin(file->f_path.mnt); 241 - acct_file_reopen(&acct_globals, file); 255 + acct_file_reopen(ns->bacct, file, ns); 242 256 spin_unlock(&acct_lock); 243 257 244 258 mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ 259 + kfree(acct); 245 260 246 261 return 0; 247 262 } ··· 287 270 error = acct_on(tmp); 288 271 putname(tmp); 289 272 } else { 273 + struct bsd_acct_struct *acct; 274 + 275 + acct = task_active_pid_ns(current)->bacct; 276 + if (acct == NULL) 277 + return 0; 278 + 290 279 error = security_acct(NULL); 291 280 if (!error) { 292 281 spin_lock(&acct_lock); 293 - acct_file_reopen(&acct_globals, NULL); 282 + acct_file_reopen(acct, NULL, NULL); 294 283 spin_unlock(&acct_lock); 295 284 } 296 285 } ··· 312 289 */ 313 290 void acct_auto_close_mnt(struct vfsmount *m) 314 291 { 292 + struct bsd_acct_struct *acct; 293 + 294 + acct = init_pid_ns.bacct; 295 + if (acct == NULL) 296 + return; 297 + 315 298 spin_lock(&acct_lock); 316 - if (acct_globals.file && acct_globals.file->f_path.mnt == m) 317 - acct_file_reopen(&acct_globals, NULL); 299 + if (acct->file && acct->file->f_path.mnt == m) 300 + acct_file_reopen(acct, NULL, NULL); 318 301 spin_unlock(&acct_lock); 319 302 } 320 303 ··· 333 304 */ 334 305 void acct_auto_close(struct super_block *sb) 335 306 { 307 + struct bsd_acct_struct *acct; 308 + 309 + acct = init_pid_ns.bacct; 310 + if (acct == NULL) 311 + return; 312 + 336 313 spin_lock(&acct_lock); 337 - if (acct_globals.file && 338 - acct_globals.file->f_path.mnt->mnt_sb == sb) { 339 - acct_file_reopen(&acct_globals, NULL); 314 + if (acct->file && acct->file->f_path.mnt->mnt_sb == sb) 315 + acct_file_reopen(acct, NULL, NULL); 316 + spin_unlock(&acct_lock); 317 + } 318 + 319 + void acct_exit_ns(struct pid_namespace *ns) 320 + { 321 + struct bsd_acct_struct *acct; 322 + 323 + spin_lock(&acct_lock); 324 + acct = ns->bacct; 325 + if (acct != NULL) { 326 + if (acct->file != NULL) 327 + acct_file_reopen(acct, NULL, NULL); 328 + 329 + kfree(acct); 340 330 } 341 331 spin_unlock(&acct_lock); 342 332 } ··· 635 587 void acct_process(void) 636 588 { 637 589 struct file *file = NULL; 638 - struct pid_namespace *ns; 590 + struct pid_namespace *ns = task_active_pid_ns(current); 591 + struct bsd_acct_struct *acct; 639 592 593 + acct = ns->bacct; 640 594 /* 641 595 * accelerate the common fastpath: 642 596 */ 643 - if (!acct_globals.file) 597 + if (!acct || !acct->file) 644 598 return; 645 599 646 600 spin_lock(&acct_lock); 647 - file = acct_globals.file; 601 + file = acct->file; 648 602 if (unlikely(!file)) { 649 603 spin_unlock(&acct_lock); 650 604 return; 651 605 } 652 606 get_file(file); 653 - ns = get_pid_ns(acct_globals.ns); 654 607 spin_unlock(&acct_lock); 655 608 656 - do_acct_process(&acct_globals, ns, file); 609 + do_acct_process(acct, ns, file); 657 610 fput(file); 658 - put_pid_ns(ns); 659 611 }
+2
kernel/pid_namespace.c
··· 12 12 #include <linux/pid_namespace.h> 13 13 #include <linux/syscalls.h> 14 14 #include <linux/err.h> 15 + #include <linux/acct.h> 15 16 16 17 #define BITS_PER_PAGE (PAGE_SIZE*8) 17 18 ··· 182 181 183 182 /* Child reaper for the pid namespace is going away */ 184 183 pid_ns->child_reaper = NULL; 184 + acct_exit_ns(pid_ns); 185 185 return; 186 186 } 187 187