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 */ _