From: Jay Lan <jlan@engr.sgi.com>

This patch is to offer common accounting data collection method at memory
usage for various accounting packages including BSD accounting, ELSA, CSA
and any other acct packages that use a common layer of data collection.

New struct fields are added to mm_struct to save high watermarks of rss
usage as well as virtual memory usage.

New struct fields are added to task_struct to collect accumulated rss usage
and vm usages.

These data are collected on per process basis.

Signed-off-by: Jay Lan <jlan@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/exec.c             |    3 +++
 25-akpm/include/linux/acct.h  |    4 ++++
 25-akpm/include/linux/mm.h    |    3 +++
 25-akpm/include/linux/sched.h |    8 ++++++++
 25-akpm/kernel/acct.c         |   32 ++++++++++++++++++++++++++++++++
 25-akpm/kernel/exit.c         |    2 ++
 25-akpm/kernel/fork.c         |    6 ++++++
 25-akpm/mm/memory.c           |   32 ++++++++++++++++++++++++++++++--
 25-akpm/mm/mmap.c             |   10 ++++++++++
 25-akpm/mm/mremap.c           |    6 ++++++
 25-akpm/mm/rmap.c             |    3 +++
 25-akpm/mm/swapfile.c         |    3 +++
 12 files changed, 110 insertions(+), 2 deletions(-)

diff -puN fs/exec.c~enhanced-memory-accounting-data-collection fs/exec.c
--- 25/fs/exec.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.048278312 -0800
+++ 25-akpm/fs/exec.c	2004-12-29 02:22:28.068275272 -0800
@@ -47,6 +47,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/rmap.h>
+#include <linux/acct.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1165,6 +1166,8 @@ int do_execve(char * filename,
 
 		/* execve success */
 		security_bprm_free(bprm);
+		acct_update_integrals();
+		update_mem_hiwater();
 		kfree(bprm);
 		return retval;
 	}
diff -puN include/linux/acct.h~enhanced-memory-accounting-data-collection include/linux/acct.h
--- 25/include/linux/acct.h~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.050278008 -0800
+++ 25-akpm/include/linux/acct.h	2004-12-29 02:22:28.069275120 -0800
@@ -120,9 +120,13 @@ struct acct_v3
 struct super_block;
 extern void acct_auto_close(struct super_block *sb);
 extern void acct_process(long exitcode);
+extern void acct_update_integrals(void);
+extern void acct_clear_integrals(struct task_struct *tsk);
 #else
 #define acct_auto_close(x)	do { } while (0)
 #define acct_process(x)		do { } while (0)
+#define acct_update_integrals()		do { } while (0)
+#define acct_clear_integrals(task)	do { } while (0)
 #endif
 
 /*
diff -puN include/linux/mm.h~enhanced-memory-accounting-data-collection include/linux/mm.h
--- 25/include/linux/mm.h~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.051277856 -0800
+++ 25-akpm/include/linux/mm.h	2004-12-29 02:22:28.070274968 -0800
@@ -856,6 +856,9 @@ static inline void vm_stat_unaccount(str
 }
 #endif
 
+/* update per process rss and vm hiwater data */
+extern void update_mem_hiwater(void);
+
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable)
diff -puN include/linux/sched.h~enhanced-memory-accounting-data-collection include/linux/sched.h
--- 25/include/linux/sched.h~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.053277552 -0800
+++ 25-akpm/include/linux/sched.h	2004-12-29 02:22:28.071274816 -0800
@@ -251,6 +251,9 @@ struct mm_struct {
 	struct kioctx		*ioctx_list;
 
 	struct kioctx		default_kioctx;
+
+	unsigned long hiwater_rss;	/* High-water RSS usage */
+	unsigned long hiwater_vm;	/* High-water virtual memory usage */
 };
 
 struct sighand_struct {
@@ -663,6 +666,11 @@ struct task_struct {
 	wait_queue_t *io_wait;
 /* i/o counters(bytes read/written, #syscalls */
 	u64 rchar, wchar, syscr, syscw;
+#if defined(CONFIG_BSD_PROCESS_ACCT)
+	u64 acct_rss_mem1;	/* accumulated rss usage */
+	u64 acct_vm_mem1;	/* accumulated virtual memory usage */
+	clock_t acct_stimexpd;	/* clock_t-converted stime since last update */
+#endif
 #ifdef CONFIG_NUMA
   	struct mempolicy *mempolicy;
   	short il_next;		/* could be shared with used_math */
diff -puN kernel/acct.c~enhanced-memory-accounting-data-collection kernel/acct.c
--- 25/kernel/acct.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.054277400 -0800
+++ 25-akpm/kernel/acct.c	2004-12-29 02:22:28.072274664 -0800
@@ -528,3 +528,35 @@ void acct_process(long exitcode)
 	do_acct_process(exitcode, file);
 	fput(file);
 }
+
+
+/*
+ * acct_update_integrals
+ *    -  update mm integral fields in task_struct
+ */
+void acct_update_integrals(void)
+{
+	long delta;
+	struct task_struct *parent = current;
+
+	if (parent->mm) {
+		delta = parent->stime - parent->acct_stimexpd;
+		parent->acct_stimexpd = parent->stime;
+		parent->acct_rss_mem1 += delta * parent->mm->rss;
+		parent->acct_vm_mem1 += delta * parent->mm->total_vm;
+	}
+}
+
+
+/*
+ * acct_clear_integrals
+ *    - clear the mm integral fields in task_struct
+ */
+void acct_clear_integrals(struct task_struct *tsk)
+{
+	if (tsk) {
+		tsk->acct_stimexpd = 0;
+		tsk->acct_rss_mem1 = 0;
+		tsk->acct_vm_mem1 = 0;
+	}
+}
diff -puN kernel/exit.c~enhanced-memory-accounting-data-collection kernel/exit.c
--- 25/kernel/exit.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.056277096 -0800
+++ 25-akpm/kernel/exit.c	2004-12-29 02:22:28.073274512 -0800
@@ -806,6 +806,8 @@ fastcall NORET_TYPE void do_exit(long co
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
 	}
 
+	acct_update_integrals();
+	update_mem_hiwater();
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
 	if (group_dead)
 		acct_process(code);
diff -puN kernel/fork.c~enhanced-memory-accounting-data-collection kernel/fork.c
--- 25/kernel/fork.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.057276944 -0800
+++ 25-akpm/kernel/fork.c	2004-12-29 02:22:28.074274360 -0800
@@ -39,6 +39,7 @@
 #include <linux/audit.h>
 #include <linux/profile.h>
 #include <linux/rmap.h>
+#include <linux/acct.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -469,6 +470,9 @@ static int copy_mm(unsigned long clone_f
 	if (retval)
 		goto free_pt;
 
+	mm->hiwater_rss = mm->rss;
+	mm->hiwater_vm = mm->total_vm;
+
 good_mm:
 	tsk->mm = mm;
 	tsk->active_mm = mm;
@@ -880,6 +884,8 @@ static task_t *copy_process(unsigned lon
 	p->wchar = 0;		/* I/O counter: bytes written */
 	p->syscr = 0;		/* I/O counter: read syscalls */
 	p->syscw = 0;		/* I/O counter: write syscalls */
+	acct_clear_integrals(p);
+
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
 	p->security = NULL;
diff -puN mm/memory.c~enhanced-memory-accounting-data-collection mm/memory.c
--- 25/mm/memory.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.059276640 -0800
+++ 25-akpm/mm/memory.c	2004-12-29 02:23:14.411230072 -0800
@@ -46,6 +46,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/rmap.h>
+#include <linux/acct.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
@@ -738,6 +739,7 @@ void zap_page_range(struct vm_area_struc
 	tlb = tlb_gather_mmu(mm, 0);
 	unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
 	tlb_finish_mmu(tlb, address, end);
+	acct_update_integrals();
 	spin_unlock(&mm->page_table_lock);
 }
 
@@ -1313,9 +1315,11 @@ static int do_wp_page(struct mm_struct *
 	if (likely(pte_same(*page_table, pte))) {
 		if (PageAnon(old_page))
 			mm->anon_rss--;
-		if (PageReserved(old_page))
+		if (PageReserved(old_page)) {
 			++mm->rss;
-		else
+			acct_update_integrals();
+			update_mem_hiwater();
+		} else
 			page_remove_rmap(old_page);
 		break_cow(vma, new_page, address, page_table);
 		lru_cache_add_active(new_page);
@@ -1597,6 +1601,9 @@ static int do_swap_page(struct mm_struct
 		remove_exclusive_swap_page(page);
 
 	mm->rss++;
+	acct_update_integrals();
+	update_mem_hiwater();
+
 	pte = mk_pte(page, vma->vm_page_prot);
 	if (write_access && can_share_swap_page(page)) {
 		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
@@ -1662,6 +1669,8 @@ do_anonymous_page(struct mm_struct *mm, 
 			goto out;
 		}
 		mm->rss++;
+		acct_update_integrals();
+		update_mem_hiwater();
 		entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
 							 vma->vm_page_prot)),
 				      vma);
@@ -1771,6 +1780,9 @@ retry:
 	if (pte_none(*page_table)) {
 		if (!PageReserved(new_page))
 			++mm->rss;
+		acct_update_integrals();
+		update_mem_hiwater();
+
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
 		if (write_access)
@@ -2053,6 +2065,22 @@ unsigned long vmalloc_to_pfn(void *vmall
 }
 EXPORT_SYMBOL(vmalloc_to_pfn);
 
+/*
+ * update_mem_hiwater
+ *	- update per process rss and vm high water data
+ */
+void update_mem_hiwater(void)
+{
+	struct task_struct *parent = current;
+
+	if (parent->mm) {
+		if (parent->mm->hiwater_rss < parent->mm->rss)
+			parent->mm->hiwater_rss = parent->mm->rss;
+		if (parent->mm->hiwater_vm < parent->mm->total_vm)
+			parent->mm->hiwater_vm = parent->mm->total_vm;
+	}
+}
+
 #if !defined(__HAVE_ARCH_GATE_AREA)
 
 #if defined(AT_SYSINFO_EHDR)
diff -puN mm/mmap.c~enhanced-memory-accounting-data-collection mm/mmap.c
--- 25/mm/mmap.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.060276488 -0800
+++ 25-akpm/mm/mmap.c	2004-12-29 02:22:28.079273600 -0800
@@ -7,6 +7,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
@@ -20,6 +21,7 @@
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
+#include <linux/acct.h>
 #include <linux/mount.h>
 #include <linux/mempolicy.h>
 #include <linux/rmap.h>
@@ -1019,6 +1021,8 @@ out:	
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
+	acct_update_integrals();
+	update_mem_hiwater();
 	return addr;
 
 unmap_and_free_vma:
@@ -1365,6 +1369,8 @@ int expand_stack(struct vm_area_struct *
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
+	acct_update_integrals();
+	update_mem_hiwater();
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1428,6 +1434,8 @@ int expand_stack(struct vm_area_struct *
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
+	acct_update_integrals();
+        update_mem_hiwater();
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1823,6 +1831,8 @@ out:
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
 	}
+	acct_update_integrals();
+	update_mem_hiwater();
 	return addr;
 }
 
diff -puN mm/mremap.c~enhanced-memory-accounting-data-collection mm/mremap.c
--- 25/mm/mremap.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.061276336 -0800
+++ 25-akpm/mm/mremap.c	2004-12-29 02:22:28.080273448 -0800
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/highmem.h>
 #include <linux/security.h>
+#include <linux/acct.h>
 #include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
@@ -248,6 +249,9 @@ static unsigned long move_vma(struct vm_
 					   new_addr + new_len);
 	}
 
+	acct_update_integrals();
+	update_mem_hiwater();
+
 	return new_addr;
 }
 
@@ -384,6 +388,8 @@ unsigned long do_mremap(unsigned long ad
 				make_pages_present(addr + old_len,
 						   addr + new_len);
 			}
+			acct_update_integrals();
+			update_mem_hiwater();
 			ret = addr;
 			goto out;
 		}
diff -puN mm/rmap.c~enhanced-memory-accounting-data-collection mm/rmap.c
--- 25/mm/rmap.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.063276032 -0800
+++ 25-akpm/mm/rmap.c	2004-12-29 02:22:28.081273296 -0800
@@ -51,6 +51,7 @@
 #include <linux/swapops.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/acct.h>
 #include <linux/rmap.h>
 #include <linux/rcupdate.h>
 
@@ -606,6 +607,7 @@ static int try_to_unmap_one(struct page 
 	}
 
 	mm->rss--;
+	acct_update_integrals();
 	page_remove_rmap(page);
 	page_cache_release(page);
 
@@ -710,6 +712,7 @@ static void try_to_unmap_cluster(unsigne
 
 		page_remove_rmap(page);
 		page_cache_release(page);
+		acct_update_integrals();
 		mm->rss--;
 		(*mapcount)--;
 	}
diff -puN mm/swapfile.c~enhanced-memory-accounting-data-collection mm/swapfile.c
--- 25/mm/swapfile.c~enhanced-memory-accounting-data-collection	2004-12-29 02:22:28.064275880 -0800
+++ 25-akpm/mm/swapfile.c	2004-12-29 02:22:28.082273144 -0800
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/rmap.h>
 #include <linux/security.h>
+#include <linux/acct.h>
 #include <linux/backing-dev.h>
 #include <linux/syscalls.h>
 
@@ -436,6 +437,8 @@ unuse_pte(struct vm_area_struct *vma, un
 	set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
 	page_add_anon_rmap(page, vma, address);
 	swap_free(entry);
+	acct_update_integrals();
+	update_mem_hiwater();
 }
 
 /* vma->vm_mm->page_table_lock is held */
_