diff options
Diffstat (limited to 'kernel/acct.c')
| -rw-r--r-- | kernel/acct.c | 125 |
1 files changed, 76 insertions, 49 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index 6802020e0ceb..f4330acead46 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -43,7 +43,6 @@ | |||
| 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> | ||
| 47 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
| 48 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
| 49 | #include <linux/acct.h> | 48 | #include <linux/acct.h> |
| @@ -75,7 +74,7 @@ int acct_parm[3] = {4, 2, 30}; | |||
| 75 | /* | 74 | /* |
| 76 | * External references and all of the globals. | 75 | * External references and all of the globals. |
| 77 | */ | 76 | */ |
| 78 | static void do_acct_process(long, struct file *); | 77 | static void do_acct_process(struct file *); |
| 79 | 78 | ||
| 80 | /* | 79 | /* |
| 81 | * 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 |
| @@ -196,7 +195,7 @@ static void acct_file_reopen(struct file *file) | |||
| 196 | if (old_acct) { | 195 | if (old_acct) { |
| 197 | mnt_unpin(old_acct->f_vfsmnt); | 196 | mnt_unpin(old_acct->f_vfsmnt); |
| 198 | spin_unlock(&acct_globals.lock); | 197 | spin_unlock(&acct_globals.lock); |
| 199 | do_acct_process(0, old_acct); | 198 | do_acct_process(old_acct); |
| 200 | filp_close(old_acct, NULL); | 199 | filp_close(old_acct, NULL); |
| 201 | spin_lock(&acct_globals.lock); | 200 | spin_lock(&acct_globals.lock); |
| 202 | } | 201 | } |
| @@ -419,16 +418,15 @@ static u32 encode_float(u64 value) | |||
| 419 | /* | 418 | /* |
| 420 | * 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. |
| 421 | */ | 420 | */ |
| 422 | static void do_acct_process(long exitcode, struct file *file) | 421 | static void do_acct_process(struct file *file) |
| 423 | { | 422 | { |
| 423 | struct pacct_struct *pacct = ¤t->signal->pacct; | ||
| 424 | acct_t ac; | 424 | acct_t ac; |
| 425 | mm_segment_t fs; | 425 | mm_segment_t fs; |
| 426 | unsigned long vsize; | ||
| 427 | unsigned long flim; | 426 | unsigned long flim; |
| 428 | u64 elapsed; | 427 | u64 elapsed; |
| 429 | u64 run_time; | 428 | u64 run_time; |
| 430 | struct timespec uptime; | 429 | struct timespec uptime; |
| 431 | unsigned long jiffies; | ||
| 432 | 430 | ||
| 433 | /* | 431 | /* |
| 434 | * First check to see if there is enough free_space to continue | 432 | * First check to see if there is enough free_space to continue |
| @@ -469,12 +467,6 @@ static void do_acct_process(long exitcode, struct file *file) | |||
| 469 | #endif | 467 | #endif |
| 470 | do_div(elapsed, AHZ); | 468 | do_div(elapsed, AHZ); |
| 471 | ac.ac_btime = xtime.tv_sec - elapsed; | 469 | ac.ac_btime = xtime.tv_sec - elapsed; |
| 472 | jiffies = cputime_to_jiffies(cputime_add(current->utime, | ||
| 473 | current->signal->utime)); | ||
| 474 | ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies)); | ||
| 475 | jiffies = cputime_to_jiffies(cputime_add(current->stime, | ||
| 476 | current->signal->stime)); | ||
| 477 | ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies)); | ||
| 478 | /* we really need to bite the bullet and change layout */ | 470 | /* we really need to bite the bullet and change layout */ |
| 479 | ac.ac_uid = current->uid; | 471 | ac.ac_uid = current->uid; |
| 480 | ac.ac_gid = current->gid; | 472 | ac.ac_gid = current->gid; |
| @@ -491,42 +483,27 @@ static void do_acct_process(long exitcode, struct file *file) | |||
| 491 | ac.ac_ppid = current->parent->tgid; | 483 | ac.ac_ppid = current->parent->tgid; |
| 492 | #endif | 484 | #endif |
| 493 | 485 | ||
| 494 | read_lock(&tasklist_lock); /* pin current->signal */ | 486 | mutex_lock(&tty_mutex); |
| 487 | /* FIXME: Whoever is responsible for current->signal locking needs | ||
| 488 | to use the same locking all over the kernel and document it */ | ||
| 489 | read_lock(&tasklist_lock); | ||
| 495 | ac.ac_tty = current->signal->tty ? | 490 | ac.ac_tty = current->signal->tty ? |
| 496 | old_encode_dev(tty_devnum(current->signal->tty)) : 0; | 491 | old_encode_dev(tty_devnum(current->signal->tty)) : 0; |
| 497 | read_unlock(&tasklist_lock); | 492 | read_unlock(&tasklist_lock); |
| 498 | 493 | mutex_unlock(&tty_mutex); | |
| 499 | ac.ac_flag = 0; | 494 | |
| 500 | if (current->flags & PF_FORKNOEXEC) | 495 | spin_lock_irq(¤t->sighand->siglock); |
| 501 | ac.ac_flag |= AFORK; | 496 | ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime))); |
| 502 | if (current->flags & PF_SUPERPRIV) | 497 | ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime))); |
| 503 | ac.ac_flag |= ASU; | 498 | ac.ac_flag = pacct->ac_flag; |
| 504 | if (current->flags & PF_DUMPCORE) | 499 | ac.ac_mem = encode_comp_t(pacct->ac_mem); |
| 505 | ac.ac_flag |= ACORE; | 500 | ac.ac_minflt = encode_comp_t(pacct->ac_minflt); |
| 506 | if (current->flags & PF_SIGNALED) | 501 | ac.ac_majflt = encode_comp_t(pacct->ac_majflt); |
| 507 | ac.ac_flag |= AXSIG; | 502 | ac.ac_exitcode = pacct->ac_exitcode; |
| 508 | 503 | spin_unlock_irq(¤t->sighand->siglock); | |
| 509 | vsize = 0; | ||
| 510 | if (current->mm) { | ||
| 511 | struct vm_area_struct *vma; | ||
| 512 | down_read(¤t->mm->mmap_sem); | ||
| 513 | vma = current->mm->mmap; | ||
| 514 | while (vma) { | ||
| 515 | vsize += vma->vm_end - vma->vm_start; | ||
| 516 | vma = vma->vm_next; | ||
| 517 | } | ||
| 518 | up_read(¤t->mm->mmap_sem); | ||
| 519 | } | ||
| 520 | vsize = vsize / 1024; | ||
| 521 | ac.ac_mem = encode_comp_t(vsize); | ||
| 522 | ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ | 504 | ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ |
| 523 | ac.ac_rw = encode_comp_t(ac.ac_io / 1024); | 505 | ac.ac_rw = encode_comp_t(ac.ac_io / 1024); |
| 524 | ac.ac_minflt = encode_comp_t(current->signal->min_flt + | ||
| 525 | current->min_flt); | ||
| 526 | ac.ac_majflt = encode_comp_t(current->signal->maj_flt + | ||
| 527 | current->maj_flt); | ||
| 528 | ac.ac_swaps = encode_comp_t(0); | 506 | ac.ac_swaps = encode_comp_t(0); |
| 529 | ac.ac_exitcode = exitcode; | ||
| 530 | 507 | ||
| 531 | /* | 508 | /* |
| 532 | * Kernel segment override to datasegment and write it | 509 | * Kernel segment override to datasegment and write it |
| @@ -546,12 +523,64 @@ static void do_acct_process(long exitcode, struct file *file) | |||
| 546 | } | 523 | } |
| 547 | 524 | ||
| 548 | /** | 525 | /** |
| 526 | * acct_init_pacct - initialize a new pacct_struct | ||
| 527 | * @pacct: per-process accounting info struct to initialize | ||
| 528 | */ | ||
| 529 | void acct_init_pacct(struct pacct_struct *pacct) | ||
| 530 | { | ||
| 531 | memset(pacct, 0, sizeof(struct pacct_struct)); | ||
| 532 | pacct->ac_utime = pacct->ac_stime = cputime_zero; | ||
| 533 | } | ||
| 534 | |||
| 535 | /** | ||
| 536 | * acct_collect - collect accounting information into pacct_struct | ||
| 537 | * @exitcode: task exit code | ||
| 538 | * @group_dead: not 0, if this thread is the last one in the process. | ||
| 539 | */ | ||
| 540 | void acct_collect(long exitcode, int group_dead) | ||
| 541 | { | ||
| 542 | struct pacct_struct *pacct = ¤t->signal->pacct; | ||
| 543 | unsigned long vsize = 0; | ||
| 544 | |||
| 545 | if (group_dead && current->mm) { | ||
| 546 | struct vm_area_struct *vma; | ||
| 547 | down_read(¤t->mm->mmap_sem); | ||
| 548 | vma = current->mm->mmap; | ||
| 549 | while (vma) { | ||
| 550 | vsize += vma->vm_end - vma->vm_start; | ||
| 551 | vma = vma->vm_next; | ||
| 552 | } | ||
| 553 | up_read(¤t->mm->mmap_sem); | ||
| 554 | } | ||
| 555 | |||
| 556 | spin_lock_irq(¤t->sighand->siglock); | ||
| 557 | if (group_dead) | ||
| 558 | pacct->ac_mem = vsize / 1024; | ||
| 559 | if (thread_group_leader(current)) { | ||
| 560 | pacct->ac_exitcode = exitcode; | ||
| 561 | if (current->flags & PF_FORKNOEXEC) | ||
| 562 | pacct->ac_flag |= AFORK; | ||
| 563 | } | ||
| 564 | if (current->flags & PF_SUPERPRIV) | ||
| 565 | pacct->ac_flag |= ASU; | ||
| 566 | if (current->flags & PF_DUMPCORE) | ||
| 567 | pacct->ac_flag |= ACORE; | ||
| 568 | if (current->flags & PF_SIGNALED) | ||
| 569 | pacct->ac_flag |= AXSIG; | ||
| 570 | pacct->ac_utime = cputime_add(pacct->ac_utime, current->utime); | ||
| 571 | pacct->ac_stime = cputime_add(pacct->ac_stime, current->stime); | ||
| 572 | pacct->ac_minflt += current->min_flt; | ||
| 573 | pacct->ac_majflt += current->maj_flt; | ||
| 574 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 575 | } | ||
| 576 | |||
| 577 | /** | ||
| 549 | * acct_process - now just a wrapper around do_acct_process | 578 | * acct_process - now just a wrapper around do_acct_process |
| 550 | * @exitcode: task exit code | 579 | * @exitcode: task exit code |
| 551 | * | 580 | * |
| 552 | * handles process accounting for an exiting task | 581 | * handles process accounting for an exiting task |
| 553 | */ | 582 | */ |
| 554 | void acct_process(long exitcode) | 583 | void acct_process(void) |
| 555 | { | 584 | { |
| 556 | struct file *file = NULL; | 585 | struct file *file = NULL; |
| 557 | 586 | ||
| @@ -570,7 +599,7 @@ void acct_process(long exitcode) | |||
| 570 | get_file(file); | 599 | get_file(file); |
| 571 | spin_unlock(&acct_globals.lock); | 600 | spin_unlock(&acct_globals.lock); |
| 572 | 601 | ||
| 573 | do_acct_process(exitcode, file); | 602 | do_acct_process(file); |
| 574 | fput(file); | 603 | fput(file); |
| 575 | } | 604 | } |
| 576 | 605 | ||
| @@ -599,9 +628,7 @@ void acct_update_integrals(struct task_struct *tsk) | |||
| 599 | */ | 628 | */ |
| 600 | void acct_clear_integrals(struct task_struct *tsk) | 629 | void acct_clear_integrals(struct task_struct *tsk) |
| 601 | { | 630 | { |
| 602 | if (tsk) { | 631 | tsk->acct_stimexpd = 0; |
| 603 | tsk->acct_stimexpd = 0; | 632 | tsk->acct_rss_mem1 = 0; |
| 604 | tsk->acct_rss_mem1 = 0; | 633 | tsk->acct_vm_mem1 = 0; |
| 605 | tsk->acct_vm_mem1 = 0; | ||
| 606 | } | ||
| 607 | } | 634 | } |
