[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
5 changed files with 51 additions and 16 deletions
|
@ -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 {
|
||||||
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 {
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
static void do_acct_process(long exitcode, struct file *file)
|
static void do_acct_process(long exitcode, struct file *file)
|
||||||
{
|
{
|
||||||
|
struct pacct_struct *pacct = ¤t->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)
|
||||||
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(¤t->sighand->siglock);
|
||||||
vsize = 0;
|
ac.ac_mem = encode_comp_t(pacct->ac_mem);
|
||||||
if (current->mm) {
|
spin_unlock(¤t->sighand->siglock);
|
||||||
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);
|
|
||||||
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)
|
||||||
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 = ¤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
|
* 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)
|
||||||
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)
|
||||||
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
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue