summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
0e46481)
When pacct facility generate an 'ac_flag' field in accounting record, it
refers a task_struct of the thread which died last in the process. But any
other task_structs are ignored.
Therefore, pacct facility drops ASU flag even if root-privilege operations are
used by any other threads except the last one. In addition, AFORK flag is
always set when the thread of group-leader didn't die last, although this
process has called execve() after fork().
We have a same matter in ac_exitcode. The recorded ac_exitcode is an exit
code of the last thread in the process. There is a possibility this exitcode
is not the group leader's one.
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_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_collect(long exitcode, int group_dead);
+extern void acct_process(void);
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)
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_collect(x,y) do { } while (0)
+#define acct_process() do { } while (0)
#define acct_update_integrals(x) do { } while (0)
#define acct_clear_integrals(task) do { } while (0)
#endif
#define acct_update_integrals(x) do { } while (0)
#define acct_clear_integrals(task) do { } while (0)
#endif
+ int ac_flag;
+ long ac_exitcode;
/*
* External references and all of the globals.
*/
/*
* External references and all of the globals.
*/
-static void do_acct_process(long, struct file *);
+static void do_acct_process(struct file *);
/*
* This structure is used so that all the data protected by lock
/*
* This structure is used so that all the data protected by lock
if (old_acct) {
mnt_unpin(old_acct->f_vfsmnt);
spin_unlock(&acct_globals.lock);
if (old_acct) {
mnt_unpin(old_acct->f_vfsmnt);
spin_unlock(&acct_globals.lock);
- do_acct_process(0, old_acct);
+ do_acct_process(old_acct);
filp_close(old_acct, NULL);
spin_lock(&acct_globals.lock);
}
filp_close(old_acct, NULL);
spin_lock(&acct_globals.lock);
}
/*
* do_acct_process does all actual work. Caller holds the reference to file.
*/
/*
* do_acct_process does all actual work. Caller holds the reference to file.
*/
-static void do_acct_process(long exitcode, struct file *file)
+static void do_acct_process(struct file *file)
{
struct pacct_struct *pacct = ¤t->signal->pacct;
acct_t ac;
{
struct pacct_struct *pacct = ¤t->signal->pacct;
acct_t ac;
old_encode_dev(tty_devnum(current->signal->tty)) : 0;
read_unlock(&tasklist_lock);
old_encode_dev(tty_devnum(current->signal->tty)) : 0;
read_unlock(&tasklist_lock);
- ac.ac_flag = 0;
- if (current->flags & PF_FORKNOEXEC)
- ac.ac_flag |= AFORK;
- if (current->flags & PF_SUPERPRIV)
- ac.ac_flag |= ASU;
- if (current->flags & PF_DUMPCORE)
- ac.ac_flag |= ACORE;
- if (current->flags & PF_SIGNALED)
- ac.ac_flag |= AXSIG;
spin_lock(¤t->sighand->siglock);
spin_lock(¤t->sighand->siglock);
+ ac.ac_flag = pacct->ac_flag;
ac.ac_mem = encode_comp_t(pacct->ac_mem);
ac.ac_mem = encode_comp_t(pacct->ac_mem);
+ ac.ac_exitcode = pacct->ac_exitcode;
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);
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_majflt = encode_comp_t(current->signal->maj_flt +
current->maj_flt);
ac.ac_swaps = encode_comp_t(0);
ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
current->maj_flt);
ac.ac_swaps = encode_comp_t(0);
- ac.ac_exitcode = exitcode;
/*
* Kernel segment override to datasegment and write it
/*
* Kernel segment override to datasegment and write it
/**
* acct_collect - collect accounting information into pacct_struct
/**
* acct_collect - collect accounting information into pacct_struct
+ * @exitcode: task exit code
+ * @group_dead: not 0, if this thread is the last one in the process.
+void acct_collect(long exitcode, int group_dead)
{
struct pacct_struct *pacct = ¤t->signal->pacct;
unsigned long vsize = 0;
{
struct pacct_struct *pacct = ¤t->signal->pacct;
unsigned long vsize = 0;
+ if (group_dead && current->mm) {
struct vm_area_struct *vma;
down_read(¤t->mm->mmap_sem);
vma = current->mm->mmap;
struct vm_area_struct *vma;
down_read(¤t->mm->mmap_sem);
vma = current->mm->mmap;
}
spin_lock(¤t->sighand->siglock);
}
spin_lock(¤t->sighand->siglock);
- pacct->ac_mem = vsize / 1024;
+ if (group_dead)
+ pacct->ac_mem = vsize / 1024;
+ if (thread_group_leader(current)) {
+ pacct->ac_exitcode = exitcode;
+ if (current->flags & PF_FORKNOEXEC)
+ pacct->ac_flag |= AFORK;
+ }
+ if (current->flags & PF_SUPERPRIV)
+ pacct->ac_flag |= ASU;
+ if (current->flags & PF_DUMPCORE)
+ pacct->ac_flag |= ACORE;
+ if (current->flags & PF_SIGNALED)
+ pacct->ac_flag |= AXSIG;
spin_unlock(¤t->sighand->siglock);
}
spin_unlock(¤t->sighand->siglock);
}
*
* handles process accounting for an exiting task
*/
*
* handles process accounting for an exiting task
*/
-void acct_process(long exitcode)
{
struct file *file = NULL;
{
struct file *file = NULL;
get_file(file);
spin_unlock(&acct_globals.lock);
get_file(file);
spin_unlock(&acct_globals.lock);
- do_acct_process(exitcode, file);
if (group_dead) {
hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
if (group_dead) {
hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
+ acct_collect(code, group_dead);
if (unlikely(tsk->robust_list))
exit_robust_list(tsk);
#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
if (unlikely(tsk->robust_list))
exit_robust_list(tsk);
#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
exit_mm(tsk);
if (group_dead)
exit_mm(tsk);
if (group_dead)
exit_sem(tsk);
__exit_files(tsk);
__exit_fs(tsk);
exit_sem(tsk);
__exit_files(tsk);
__exit_fs(tsk);