The patch titled pacct: add pacct_struct to fix some pacct bugs. has been added to the -mm tree. Its filename is pacct-two-phase-process-accounting.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: pacct: add pacct_struct to fix some pacct bugs. From: KaiGai Kohei <kaigai@xxxxxxxxxxxxx> 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. ---- in kernel/exit.c : do_exit() ------------ group_dead = atomic_dec_and_test(&tsk->signal->live); if (group_dead) { hrtimer_cancel(&tsk->signal->real_timer); exit_itimers(tsk->signal); acct_process(code); } : - snip - : exit_mm(tsk); ---------------------------------------------- This patch separates generating an accounting record facility into two-phase. In the first one, acct_collect() calculate vitual memory size of the process and stores it into pacct_struct before exit_mm(). Then, acct_process() generates an accounting record and write it into medium. Signed-off-by: KaiGai Kohei <kaigai@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- include/linux/acct.h | 4 +++ include/linux/sched.h | 7 +++++ kernel/acct.c | 51 ++++++++++++++++++++++++++++------------ kernel/exit.c | 4 ++- kernel/fork.c | 1 5 files changed, 51 insertions(+), 16 deletions(-) diff -puN include/linux/acct.h~pacct-two-phase-process-accounting include/linux/acct.h --- a/include/linux/acct.h~pacct-two-phase-process-accounting +++ a/include/linux/acct.h @@ -121,12 +121,16 @@ struct vfsmount; struct super_block; extern void acct_auto_close_mnt(struct vfsmount *m); extern void acct_auto_close(struct super_block *sb); +extern void acct_init_pacct(struct pacct_struct *pacct); +extern void acct_collect(); extern void acct_process(long exitcode); extern void acct_update_integrals(struct task_struct *tsk); extern void acct_clear_integrals(struct task_struct *tsk); #else #define acct_auto_close_mnt(x) do { } while (0) #define acct_auto_close(x) do { } while (0) +#define acct_init_pacct(x) do { } while (0) +#define acct_collect() do { } while (0) #define acct_process(x) do { } while (0) #define acct_update_integrals(x) do { } while (0) #define acct_clear_integrals(task) do { } while (0) diff -puN include/linux/sched.h~pacct-two-phase-process-accounting include/linux/sched.h --- a/include/linux/sched.h~pacct-two-phase-process-accounting +++ a/include/linux/sched.h @@ -358,6 +358,10 @@ struct sighand_struct { spinlock_t siglock; }; +struct pacct_struct { + unsigned long ac_mem; +}; + /* * NOTE! "signal_struct" does not have it's own * locking, because a shared signal_struct always @@ -449,6 +453,9 @@ struct signal_struct { struct key *session_keyring; /* keyring inherited over fork */ struct key *process_keyring; /* keyring private to this process */ #endif +#ifdef CONFIG_BSD_PROCESS_ACCT + struct pacct_struct pacct; /* per-process accounting information */ +#endif }; /* Context switch must be unlocked if interrupts are to be enabled */ diff -puN kernel/acct.c~pacct-two-phase-process-accounting kernel/acct.c --- a/kernel/acct.c~pacct-two-phase-process-accounting +++ a/kernel/acct.c @@ -421,9 +421,9 @@ static u32 encode_float(u64 value) */ static void do_acct_process(long exitcode, struct file *file) { + struct pacct_struct *pacct = ¤t->signal->pacct; acct_t ac; mm_segment_t fs; - unsigned long vsize; unsigned long flim; u64 elapsed; u64 run_time; @@ -505,20 +505,9 @@ static void do_acct_process(long exitcod ac.ac_flag |= ACORE; if (current->flags & PF_SIGNALED) ac.ac_flag |= AXSIG; - - vsize = 0; - if (current->mm) { - struct vm_area_struct *vma; - down_read(¤t->mm->mmap_sem); - vma = current->mm->mmap; - while (vma) { - vsize += vma->vm_end - vma->vm_start; - vma = vma->vm_next; - } - up_read(¤t->mm->mmap_sem); - } - vsize = vsize / 1024; - ac.ac_mem = encode_comp_t(vsize); + spin_lock(¤t->sighand->siglock); + ac.ac_mem = encode_comp_t(pacct->ac_mem); + spin_unlock(¤t->sighand->siglock); ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ ac.ac_rw = encode_comp_t(ac.ac_io / 1024); ac.ac_minflt = encode_comp_t(current->signal->min_flt + @@ -546,6 +535,38 @@ static void do_acct_process(long exitcod } /** + * acct_init_pacct - initialize a new pacct_struct + */ +void acct_init_pacct(struct pacct_struct *pacct) +{ + memset(pacct, 0, sizeof(struct pacct_struct)); +} + +/** + * acct_collect - collect accounting information into pacct_struct + */ +void acct_collect(void) +{ + struct pacct_struct *pacct = ¤t->signal->pacct; + unsigned long vsize = 0; + + if (current->mm) { + struct vm_area_struct *vma; + down_read(¤t->mm->mmap_sem); + vma = current->mm->mmap; + while (vma) { + vsize += vma->vm_end - vma->vm_start; + vma = vma->vm_next; + } + up_read(¤t->mm->mmap_sem); + } + + spin_lock(¤t->sighand->siglock); + pacct->ac_mem = vsize / 1024; + spin_unlock(¤t->sighand->siglock); +} + +/** * acct_process - now just a wrapper around do_acct_process * @exitcode: task exit code * diff -puN kernel/exit.c~pacct-two-phase-process-accounting kernel/exit.c --- a/kernel/exit.c~pacct-two-phase-process-accounting +++ a/kernel/exit.c @@ -894,7 +894,7 @@ fastcall NORET_TYPE void do_exit(long co if (group_dead) { hrtimer_cancel(&tsk->signal->real_timer); exit_itimers(tsk->signal); - acct_process(code); + acct_collect(); } if (unlikely(tsk->robust_list)) exit_robust_list(tsk); @@ -906,6 +906,8 @@ fastcall NORET_TYPE void do_exit(long co audit_free(tsk); exit_mm(tsk); + if (group_dead) + acct_process(code); exit_sem(tsk); __exit_files(tsk); __exit_fs(tsk); diff -puN kernel/fork.c~pacct-two-phase-process-accounting kernel/fork.c --- a/kernel/fork.c~pacct-two-phase-process-accounting +++ a/kernel/fork.c @@ -874,6 +874,7 @@ static inline int copy_signal(unsigned l tsk->it_prof_expires = secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur); } + acct_init_pacct(&sig->pacct); return 0; } _ Patches currently in -mm which might be from kaigai@xxxxxxxxxxxxx are origin.patch pacct-two-phase-process-accounting.patch pacct-avoidance-to-refer-the-last-thread-as-a-representation-of-the-process.patch pacct-none-delayed-process-accounting-accumulation.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html