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;
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)
......
......@@ -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 */
......
......@@ -421,9 +421,9 @@ static u32 encode_float(u64 value)
*/
static void do_acct_process(long exitcode, struct file *file)
{
struct pacct_struct *pacct = &current->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 exitcode, struct file *file)
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(&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);
spin_lock(&current->sighand->siglock);
ac.ac_mem = encode_comp_t(pacct->ac_mem);
spin_unlock(&current->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 +
......@@ -545,6 +534,38 @@ static void do_acct_process(long exitcode, struct file *file)
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
* @exitcode: task exit code
......
......@@ -894,7 +894,7 @@ fastcall NORET_TYPE void do_exit(long code)
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 code)
audit_free(tsk);
exit_mm(tsk);
if (group_dead)
acct_process(code);
exit_sem(tsk);
__exit_files(tsk);
__exit_fs(tsk);
......
......@@ -874,6 +874,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
tsk->it_prof_expires =
secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
}
acct_init_pacct(&sig->pacct);
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