diff options
author | KaiGai Kohei <kaigai@ak.jp.nec.com> | 2006-06-25 08:49:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:01:25 -0400 |
commit | 0e4648141af02331f21aabcd34940c70f09a2d04 (patch) | |
tree | 3e4dea992a8e3f3194be04a0fd3e14c24a313ee7 | |
parent | 6bc392741d661eb84be503d1fdf14b6746615e4c (diff) |
[PATCH] pacct: add pacct_struct to fix some pacct bugs.
The pacct facility need an i/o operation when an accounting record is
generated. There is a possibility to wake OOM killer up. If OOM killer is
activated, it kills some processes to make them release process memory
regions.
But acct_process() is called in the killed processes context before calling
exit_mm(), so those processes cannot release own memory. In the results, any
processes stop in this point and it finally cause a system stall.
-rw-r--r-- | include/linux/acct.h | 4 | ||||
-rw-r--r-- | include/linux/sched.h | 7 | ||||
-rw-r--r-- | kernel/acct.c | 51 | ||||
-rw-r--r-- | kernel/exit.c | 4 | ||||
-rw-r--r-- | kernel/fork.c | 1 |
5 files changed, 51 insertions, 16 deletions
diff --git a/include/linux/acct.h b/include/linux/acct.h index 3d54fbcf969e..5bca9b3ef2d7 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
@@ -121,12 +121,16 @@ struct vfsmount; | |||
121 | struct super_block; | 121 | struct super_block; |
122 | extern void acct_auto_close_mnt(struct vfsmount *m); | 122 | extern void acct_auto_close_mnt(struct vfsmount *m); |
123 | extern void acct_auto_close(struct super_block *sb); | 123 | extern void acct_auto_close(struct super_block *sb); |
124 | extern void acct_init_pacct(struct pacct_struct *pacct); | ||
125 | extern void acct_collect(); | ||
124 | extern void acct_process(long exitcode); | 126 | extern void acct_process(long exitcode); |
125 | extern void acct_update_integrals(struct task_struct *tsk); | 127 | extern void acct_update_integrals(struct task_struct *tsk); |
126 | extern void acct_clear_integrals(struct task_struct *tsk); | 128 | extern void acct_clear_integrals(struct task_struct *tsk); |
127 | #else | 129 | #else |
128 | #define acct_auto_close_mnt(x) do { } while (0) | 130 | #define acct_auto_close_mnt(x) do { } while (0) |
129 | #define acct_auto_close(x) do { } while (0) | 131 | #define acct_auto_close(x) do { } while (0) |
132 | #define acct_init_pacct(x) do { } while (0) | ||
133 | #define acct_collect() do { } while (0) | ||
130 | #define acct_process(x) do { } while (0) | 134 | #define acct_process(x) do { } while (0) |
131 | #define acct_update_integrals(x) do { } while (0) | 135 | #define acct_update_integrals(x) do { } while (0) |
132 | #define acct_clear_integrals(task) do { } while (0) | 136 | #define acct_clear_integrals(task) do { } while (0) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 38b4791e6a5d..abada7c1d5e4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -358,6 +358,10 @@ struct sighand_struct { | |||
358 | spinlock_t siglock; | 358 | spinlock_t siglock; |
359 | }; | 359 | }; |
360 | 360 | ||
361 | struct pacct_struct { | ||
362 | unsigned long ac_mem; | ||
363 | }; | ||
364 | |||
361 | /* | 365 | /* |
362 | * NOTE! "signal_struct" does not have it's own | 366 | * NOTE! "signal_struct" does not have it's own |
363 | * locking, because a shared signal_struct always | 367 | * locking, because a shared signal_struct always |
@@ -449,6 +453,9 @@ struct signal_struct { | |||
449 | struct key *session_keyring; /* keyring inherited over fork */ | 453 | struct key *session_keyring; /* keyring inherited over fork */ |
450 | struct key *process_keyring; /* keyring private to this process */ | 454 | struct key *process_keyring; /* keyring private to this process */ |
451 | #endif | 455 | #endif |
456 | #ifdef CONFIG_BSD_PROCESS_ACCT | ||
457 | struct pacct_struct pacct; /* per-process accounting information */ | ||
458 | #endif | ||
452 | }; | 459 | }; |
453 | 460 | ||
454 | /* Context switch must be unlocked if interrupts are to be enabled */ | 461 | /* Context switch must be unlocked if interrupts are to be enabled */ |
diff --git a/kernel/acct.c b/kernel/acct.c index 44dd6bd63517..b35263137824 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -421,9 +421,9 @@ static u32 encode_float(u64 value) | |||
421 | */ | 421 | */ |
422 | static void do_acct_process(long exitcode, struct file *file) | 422 | static void do_acct_process(long exitcode, struct file *file) |
423 | { | 423 | { |
424 | struct pacct_struct *pacct = ¤t->signal->pacct; | ||
424 | acct_t ac; | 425 | acct_t ac; |
425 | mm_segment_t fs; | 426 | mm_segment_t fs; |
426 | unsigned long vsize; | ||
427 | unsigned long flim; | 427 | unsigned long flim; |
428 | u64 elapsed; | 428 | u64 elapsed; |
429 | u64 run_time; | 429 | u64 run_time; |
@@ -505,20 +505,9 @@ static void do_acct_process(long exitcode, struct file *file) | |||
505 | ac.ac_flag |= ACORE; | 505 | ac.ac_flag |= ACORE; |
506 | if (current->flags & PF_SIGNALED) | 506 | if (current->flags & PF_SIGNALED) |
507 | ac.ac_flag |= AXSIG; | 507 | ac.ac_flag |= AXSIG; |
508 | 508 | spin_lock(¤t->sighand->siglock); | |
509 | vsize = 0; | 509 | ac.ac_mem = encode_comp_t(pacct->ac_mem); |
510 | if (current->mm) { | 510 | spin_unlock(¤t->sighand->siglock); |
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 */); /* %% */ | 511 | ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ |
523 | ac.ac_rw = encode_comp_t(ac.ac_io / 1024); | 512 | ac.ac_rw = encode_comp_t(ac.ac_io / 1024); |
524 | ac.ac_minflt = encode_comp_t(current->signal->min_flt + | 513 | ac.ac_minflt = encode_comp_t(current->signal->min_flt + |
@@ -546,6 +535,38 @@ static void do_acct_process(long exitcode, struct file *file) | |||
546 | } | 535 | } |
547 | 536 | ||
548 | /** | 537 | /** |
538 | * acct_init_pacct - initialize a new pacct_struct | ||
539 | */ | ||
540 | void acct_init_pacct(struct pacct_struct *pacct) | ||
541 | { | ||
542 | memset(pacct, 0, sizeof(struct pacct_struct)); | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * acct_collect - collect accounting information into pacct_struct | ||
547 | */ | ||
548 | void acct_collect(void) | ||
549 | { | ||
550 | struct pacct_struct *pacct = ¤t->signal->pacct; | ||
551 | unsigned long vsize = 0; | ||
552 | |||
553 | if (current->mm) { | ||
554 | struct vm_area_struct *vma; | ||
555 | down_read(¤t->mm->mmap_sem); | ||
556 | vma = current->mm->mmap; | ||
557 | while (vma) { | ||
558 | vsize += vma->vm_end - vma->vm_start; | ||
559 | vma = vma->vm_next; | ||
560 | } | ||
561 | up_read(¤t->mm->mmap_sem); | ||
562 | } | ||
563 | |||
564 | spin_lock(¤t->sighand->siglock); | ||
565 | pacct->ac_mem = vsize / 1024; | ||
566 | spin_unlock(¤t->sighand->siglock); | ||
567 | } | ||
568 | |||
569 | /** | ||
549 | * acct_process - now just a wrapper around do_acct_process | 570 | * acct_process - now just a wrapper around do_acct_process |
550 | * @exitcode: task exit code | 571 | * @exitcode: task exit code |
551 | * | 572 | * |
diff --git a/kernel/exit.c b/kernel/exit.c index 601263c0806f..819d82c2efba 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -894,7 +894,7 @@ fastcall NORET_TYPE void do_exit(long code) | |||
894 | if (group_dead) { | 894 | if (group_dead) { |
895 | hrtimer_cancel(&tsk->signal->real_timer); | 895 | hrtimer_cancel(&tsk->signal->real_timer); |
896 | exit_itimers(tsk->signal); | 896 | exit_itimers(tsk->signal); |
897 | acct_process(code); | 897 | acct_collect(); |
898 | } | 898 | } |
899 | if (unlikely(tsk->robust_list)) | 899 | if (unlikely(tsk->robust_list)) |
900 | exit_robust_list(tsk); | 900 | exit_robust_list(tsk); |
@@ -906,6 +906,8 @@ fastcall NORET_TYPE void do_exit(long code) | |||
906 | audit_free(tsk); | 906 | audit_free(tsk); |
907 | exit_mm(tsk); | 907 | exit_mm(tsk); |
908 | 908 | ||
909 | if (group_dead) | ||
910 | acct_process(code); | ||
909 | exit_sem(tsk); | 911 | exit_sem(tsk); |
910 | __exit_files(tsk); | 912 | __exit_files(tsk); |
911 | __exit_fs(tsk); | 913 | __exit_fs(tsk); |
diff --git a/kernel/fork.c b/kernel/fork.c index 49adc0e8d47c..dfd10cb370c3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -874,6 +874,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
874 | tsk->it_prof_expires = | 874 | tsk->it_prof_expires = |
875 | secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur); | 875 | secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur); |
876 | } | 876 | } |
877 | acct_init_pacct(&sig->pacct); | ||
877 | 878 | ||
878 | return 0; | 879 | return 0; |
879 | } | 880 | } |