Commit 0e464814 authored by KaiGai Kohei's avatar KaiGai Kohei Committed by Linus Torvalds

[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.
parent 6bc39274
...@@ -121,12 +121,16 @@ struct vfsmount; ...@@ -121,12 +121,16 @@ struct vfsmount;
struct super_block; struct super_block;
extern void acct_auto_close_mnt(struct vfsmount *m); extern void acct_auto_close_mnt(struct vfsmount *m);
extern void acct_auto_close(struct super_block *sb); 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_process(long exitcode);
extern void acct_update_integrals(struct task_struct *tsk); extern void acct_update_integrals(struct task_struct *tsk);
extern void acct_clear_integrals(struct task_struct *tsk); extern void acct_clear_integrals(struct task_struct *tsk);
#else #else
#define acct_auto_close_mnt(x) do { } while (0) #define acct_auto_close_mnt(x) do { } while (0)
#define acct_auto_close(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_process(x) do { } while (0)
#define acct_update_integrals(x) do { } while (0) #define acct_update_integrals(x) do { } while (0)
#define acct_clear_integrals(task) do { } while (0) #define acct_clear_integrals(task) do { } while (0)
......
...@@ -358,6 +358,10 @@ struct sighand_struct { ...@@ -358,6 +358,10 @@ struct sighand_struct {
spinlock_t siglock; spinlock_t siglock;
}; };
struct pacct_struct {
unsigned long ac_mem;
};
/* /*
* NOTE! "signal_struct" does not have it's own * NOTE! "signal_struct" does not have it's own
* locking, because a shared signal_struct always * locking, because a shared signal_struct always
...@@ -449,6 +453,9 @@ struct signal_struct { ...@@ -449,6 +453,9 @@ struct signal_struct {
struct key *session_keyring; /* keyring inherited over fork */ struct key *session_keyring; /* keyring inherited over fork */
struct key *process_keyring; /* keyring private to this process */ struct key *process_keyring; /* keyring private to this process */
#endif #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 */ /* Context switch must be unlocked if interrupts are to be enabled */
......
...@@ -421,9 +421,9 @@ static u32 encode_float(u64 value) ...@@ -421,9 +421,9 @@ static u32 encode_float(u64 value)
*/ */
static void do_acct_process(long exitcode, struct file *file) static void do_acct_process(long exitcode, struct file *file)
{ {
struct pacct_struct *pacct = &current->signal->pacct;
acct_t ac; acct_t ac;
mm_segment_t fs; mm_segment_t fs;
unsigned long vsize;
unsigned long flim; unsigned long flim;
u64 elapsed; u64 elapsed;
u64 run_time; u64 run_time;
...@@ -505,20 +505,9 @@ static void do_acct_process(long exitcode, struct file *file) ...@@ -505,20 +505,9 @@ static void do_acct_process(long exitcode, struct file *file)
ac.ac_flag |= ACORE; ac.ac_flag |= ACORE;
if (current->flags & PF_SIGNALED) if (current->flags & PF_SIGNALED)
ac.ac_flag |= AXSIG; ac.ac_flag |= AXSIG;
spin_lock(&current->sighand->siglock);
vsize = 0; ac.ac_mem = encode_comp_t(pacct->ac_mem);
if (current->mm) { spin_unlock(&current->sighand->siglock);
struct vm_area_struct *vma;
down_read(&current->mm->mmap_sem);
vma = current->mm->mmap;
while (vma) {
vsize += vma->vm_end - vma->vm_start;
vma = vma->vm_next;
}
up_read(&current->mm->mmap_sem);
}
vsize = vsize / 1024;
ac.ac_mem = encode_comp_t(vsize);
ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
ac.ac_rw = encode_comp_t(ac.ac_io / 1024); ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
ac.ac_minflt = encode_comp_t(current->signal->min_flt + ac.ac_minflt = encode_comp_t(current->signal->min_flt +
...@@ -545,6 +534,38 @@ static void do_acct_process(long exitcode, struct file *file) ...@@ -545,6 +534,38 @@ static void do_acct_process(long exitcode, struct file *file)
set_fs(fs); set_fs(fs);
} }
/**
* 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 = &current->signal->pacct;
unsigned long vsize = 0;
if (current->mm) {
struct vm_area_struct *vma;
down_read(&current->mm->mmap_sem);
vma = current->mm->mmap;
while (vma) {
vsize += vma->vm_end - vma->vm_start;
vma = vma->vm_next;
}
up_read(&current->mm->mmap_sem);
}
spin_lock(&current->sighand->siglock);
pacct->ac_mem = vsize / 1024;
spin_unlock(&current->sighand->siglock);
}
/** /**
* acct_process - now just a wrapper around do_acct_process * acct_process - now just a wrapper around do_acct_process
* @exitcode: task exit code * @exitcode: task exit code
......
...@@ -894,7 +894,7 @@ fastcall NORET_TYPE void do_exit(long code) ...@@ -894,7 +894,7 @@ fastcall NORET_TYPE void do_exit(long code)
if (group_dead) { if (group_dead) {
hrtimer_cancel(&tsk->signal->real_timer); hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal); exit_itimers(tsk->signal);
acct_process(code); acct_collect();
} }
if (unlikely(tsk->robust_list)) if (unlikely(tsk->robust_list))
exit_robust_list(tsk); exit_robust_list(tsk);
...@@ -906,6 +906,8 @@ fastcall NORET_TYPE void do_exit(long code) ...@@ -906,6 +906,8 @@ fastcall NORET_TYPE void do_exit(long code)
audit_free(tsk); audit_free(tsk);
exit_mm(tsk); exit_mm(tsk);
if (group_dead)
acct_process(code);
exit_sem(tsk); exit_sem(tsk);
__exit_files(tsk); __exit_files(tsk);
__exit_fs(tsk); __exit_fs(tsk);
......
...@@ -874,6 +874,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts ...@@ -874,6 +874,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
tsk->it_prof_expires = tsk->it_prof_expires =
secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur); secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
} }
acct_init_pacct(&sig->pacct);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment