Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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)
+7 −0
Original line number Diff line number Diff line
@@ -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 */
+36 −15
Original line number Diff line number Diff line
@@ -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
+3 −1
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;
}