Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1054

kernel-2.6.18-238.el5.src.rpm

From: Amerigo Wang <amwang@redhat.com>
Date: Thu, 10 Dec 2009 08:29:09 -0500
Subject: [fs] getrusage: fill ru_maxrss value
Message-id: <20091210083211.4058.98229.sendpatchset@localhost.localdomain>
Patchwork-id: 21835
O-Subject: [PATCH RHEL5.x] getrusage: fill ru_maxrss value
Bugzilla: 466157
RH-Acked-by: Jiri Pirko <jpirko@redhat.com>
RH-Acked-by: Jerome Marchand <jmarchan@redhat.com>

BZ:
https://bugzilla.redhat.com/show_bug.cgi?id=466157

Description:
/usr/bin/time should report meaningful results for
ru_maxrss etc. fields. Both Jiri and I tried to fill
ru_ixrss etc. fields, but upstream doesn't like this.
Also, it is not easy to get a correct value for those
fields, because in kernel we don't have such statistics
currently. So only for ru_maxrss.

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=2143278

Upstream status:
Commit 1f10206cf8e945220f7220a809d8bfc15c21f9a5

Test status:
With the testcase from Jiri [1], I can see getrusage()
gets a proper value for ru_maxrss field now.

1. http://lkml.org/lkml/2008/12/30/79

Signed-off-by: WANG Cong <amwang@redhat.com>


diff --git a/fs/exec.c b/fs/exec.c
index 36bf8ad..3ab76d4 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -925,6 +925,9 @@ static int de_thread(struct task_struct *tsk)
 	sig->flags = 0;
 
 no_thread_group:
+	if (current->mm)
+		setmax_mm_hiwater_rss(&signal_aux(sig)->maxrss, current->mm);
+
 	exit_itimers(sig);
 	if (leader)
 		release_task(leader);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 49cfe5e..53683be 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -416,6 +416,20 @@ struct mm_struct {
 	struct kioctx		*ioctx_list;
 };
 
+static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm)
+{
+	return max(mm->hiwater_rss, get_mm_rss(mm));
+}
+
+static inline void setmax_mm_hiwater_rss(unsigned long *maxrss,
+					struct mm_struct *mm)
+{
+	unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
+
+	if (*maxrss < hiwater_rss)
+		*maxrss = hiwater_rss;
+}
+
 struct sighand_struct {
 	atomic_t		count;
 	struct k_sigaction	action[_NSIG];
@@ -538,6 +552,7 @@ struct signal_struct {
 
 struct signal_struct_aux {
 	u64 rchar, wchar, syscr, syscw;
+	unsigned long maxrss, cmaxrss;
 	struct task_io_accounting ioac;
 	u32 it_prof_error, it_prof_incr_error;
 	u32 it_virt_error, it_virt_incr_error;
diff --git a/kernel/exit.c b/kernel/exit.c
index a68d910..695fbe4 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -887,6 +887,9 @@ fastcall NORET_TYPE void do_exit(long code)
 	if (group_dead) {
 		hrtimer_cancel(&tsk->signal->real_timer);
 		exit_itimers(tsk->signal);
+		if (tsk->mm)
+			setmax_mm_hiwater_rss(&signal_aux(tsk->signal)->maxrss,
+						tsk->mm);
 	}
 
 	if (current->tux_info) {
@@ -1147,6 +1150,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
 	if (likely(p->signal)) {
 		struct signal_struct *psig;
 		struct signal_struct *sig;
+		unsigned long maxrss;
 
 		/*
 		 * The resource counters for the group leader are in its
@@ -1192,6 +1196,9 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
 			paux->wchar += p->wchar + aux->wchar;
 			paux->syscr += p->syscr + aux->syscr;
 			paux->syscw += p->syscw + aux->syscw;
+			maxrss = max(aux->maxrss, aux->cmaxrss);
+			if (paux->cmaxrss < maxrss)
+				paux->cmaxrss = maxrss;
 #ifdef CONFIG_TASK_IO_ACCOUNTING
 			paux->ioac.read_bytes +=
 				task_aux(p)->ioac.read_bytes +
diff --git a/kernel/sys.c b/kernel/sys.c
index 6f7d3f1..98a8608 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1899,12 +1899,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 	struct task_struct *t;
 	unsigned long flags;
 	cputime_t utime, stime;
+	unsigned long maxrss = 0;
 
 	memset((char *) r, 0, sizeof *r);
 	utime = stime = cputime_zero;
 
 	if (who == RUSAGE_THREAD) {
 		accumulate_thread_rusage(p, r, &utime, &stime);
+		maxrss = signal_aux(p->signal)->maxrss;
 		goto out;
 	}
 
@@ -1923,6 +1925,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 			r->ru_nivcsw = p->signal->cnivcsw;
 			r->ru_minflt = p->signal->cmin_flt;
 			r->ru_majflt = p->signal->cmaj_flt;
+			maxrss = signal_aux(p->signal)->cmaxrss;
 
 			if (who == RUSAGE_CHILDREN)
 				break;
@@ -1934,6 +1937,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 			r->ru_nivcsw += p->signal->nivcsw;
 			r->ru_minflt += p->signal->min_flt;
 			r->ru_majflt += p->signal->maj_flt;
+			if (maxrss < signal_aux(p->signal)->maxrss)
+				maxrss = signal_aux(p->signal)->maxrss;
 			t = p;
 			do {
 				accumulate_thread_rusage(t, r, &utime, &stime);
@@ -1951,6 +1956,15 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 out:
 	cputime_to_timeval(utime, &r->ru_utime);
 	cputime_to_timeval(stime, &r->ru_stime);
+
+	if (who != RUSAGE_CHILDREN) {
+		struct mm_struct *mm = get_task_mm(p);
+		if (mm) {
+			setmax_mm_hiwater_rss(&maxrss, mm);
+			mmput(mm);
+		}
+	}
+	r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
 }
 
 int getrusage(struct task_struct *p, int who, struct rusage __user *ru)