From: Jay Lan 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 Signed-off-by: Andrew Morton --- 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 | 34 ++++++++++++++++++++++++++++++++-- 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, 112 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-03 20:55:52.120957984 -0800 +++ 25-akpm/fs/exec.c 2004-12-03 20:55:52.140954944 -0800 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -1164,6 +1165,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-03 20:55:52.121957832 -0800 +++ 25-akpm/include/linux/acct.h 2004-12-03 20:55:52.141954792 -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-03 20:55:52.123957528 -0800 +++ 25-akpm/include/linux/mm.h 2004-12-03 20:55:52.142954640 -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-03 20:55:52.124957376 -0800 +++ 25-akpm/include/linux/sched.h 2004-12-03 20:55:52.213943848 -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-03 20:55:52.126957072 -0800 +++ 25-akpm/kernel/acct.c 2004-12-03 20:55:52.214943696 -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-03 20:55:52.127956920 -0800 +++ 25-akpm/kernel/exit.c 2004-12-03 20:55:52.215943544 -0800 @@ -807,6 +807,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-03 20:55:52.129956616 -0800 +++ 25-akpm/kernel/fork.c 2004-12-03 20:55:52.216943392 -0800 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -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-03 20:55:52.130956464 -0800 +++ 25-akpm/mm/memory.c 2004-12-03 20:55:52.218943088 -0800 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -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,24 @@ 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(CONFIG_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-03 20:55:52.132956160 -0800 +++ 25-akpm/mm/mmap.c 2004-12-03 20:55:52.220942784 -0800 @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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-03 20:55:52.133956008 -0800 +++ 25-akpm/mm/mremap.c 2004-12-03 20:55:52.220942784 -0800 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -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-03 20:55:52.135955704 -0800 +++ 25-akpm/mm/rmap.c 2004-12-03 20:55:52.221942632 -0800 @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -603,6 +604,7 @@ static int try_to_unmap_one(struct page } mm->rss--; + acct_update_integrals(); page_remove_rmap(page); page_cache_release(page); @@ -707,6 +709,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-03 20:55:52.136955552 -0800 +++ 25-akpm/mm/swapfile.c 2004-12-03 20:55:52.222942480 -0800 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -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 */ _