aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-06-25 08:49:24 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:01:25 -0400
commit0e4648141af02331f21aabcd34940c70f09a2d04 (patch)
tree3e4dea992a8e3f3194be04a0fd3e14c24a313ee7
parent6bc392741d661eb84be503d1fdf14b6746615e4c (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.h4
-rw-r--r--include/linux/sched.h7
-rw-r--r--kernel/acct.c51
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/fork.c1
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;
121struct super_block; 121struct super_block;
122extern void acct_auto_close_mnt(struct vfsmount *m); 122extern void acct_auto_close_mnt(struct vfsmount *m);
123extern void acct_auto_close(struct super_block *sb); 123extern void acct_auto_close(struct super_block *sb);
124extern void acct_init_pacct(struct pacct_struct *pacct);
125extern void acct_collect();
124extern void acct_process(long exitcode); 126extern void acct_process(long exitcode);
125extern void acct_update_integrals(struct task_struct *tsk); 127extern void acct_update_integrals(struct task_struct *tsk);
126extern void acct_clear_integrals(struct task_struct *tsk); 128extern 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
361struct 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 */
422static void do_acct_process(long exitcode, struct file *file) 422static void do_acct_process(long exitcode, struct file *file)
423{ 423{
424 struct pacct_struct *pacct = &current->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(&current->sighand->siglock);
509 vsize = 0; 509 ac.ac_mem = encode_comp_t(pacct->ac_mem);
510 if (current->mm) { 510 spin_unlock(&current->sighand->siglock);
511 struct vm_area_struct *vma;
512 down_read(&current->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(&current->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 */
540void 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 */
548void acct_collect(void)
549{
550 struct pacct_struct *pacct = &current->signal->pacct;
551 unsigned long vsize = 0;
552
553 if (current->mm) {
554 struct vm_area_struct *vma;
555 down_read(&current->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(&current->mm->mmap_sem);
562 }
563
564 spin_lock(&current->sighand->siglock);
565 pacct->ac_mem = vsize / 1024;
566 spin_unlock(&current->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}