[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.
This commit is contained in:
parent
6bc392741d
commit
0e4648141a
|
@ -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 = ¤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 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(¤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 +
|
||||
|
@ -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 = ¤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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue