Commit b6a6107a authored by Jay Lan's avatar Jay Lan Committed by Linus Torvalds

[PATCH] enhanced Memory accounting data collection

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: default avatarJay Lan <jlan@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9ca7d6f6
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/rmap.h> #include <linux/rmap.h>
#include <linux/acct.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
...@@ -1165,6 +1166,8 @@ int do_execve(char * filename, ...@@ -1165,6 +1166,8 @@ int do_execve(char * filename,
/* execve success */ /* execve success */
security_bprm_free(bprm); security_bprm_free(bprm);
acct_update_integrals();
update_mem_hiwater();
kfree(bprm); kfree(bprm);
return retval; return retval;
} }
......
...@@ -120,9 +120,13 @@ struct acct_v3 ...@@ -120,9 +120,13 @@ struct acct_v3
struct super_block; struct super_block;
extern void acct_auto_close(struct super_block *sb); extern void acct_auto_close(struct super_block *sb);
extern void acct_process(long exitcode); extern void acct_process(long exitcode);
extern void acct_update_integrals(void);
extern void acct_clear_integrals(struct task_struct *tsk);
#else #else
#define acct_auto_close(x) do { } while (0) #define acct_auto_close(x) do { } while (0)
#define acct_process(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 #endif
/* /*
......
...@@ -833,6 +833,9 @@ static inline void vm_stat_unaccount(struct vm_area_struct *vma) ...@@ -833,6 +833,9 @@ static inline void vm_stat_unaccount(struct vm_area_struct *vma)
-vma_pages(vma)); -vma_pages(vma));
} }
/* update per process rss and vm hiwater data */
extern void update_mem_hiwater(void);
#ifndef CONFIG_DEBUG_PAGEALLOC #ifndef CONFIG_DEBUG_PAGEALLOC
static inline void static inline void
kernel_map_pages(struct page *page, int numpages, int enable) kernel_map_pages(struct page *page, int numpages, int enable)
......
...@@ -250,6 +250,9 @@ struct mm_struct { ...@@ -250,6 +250,9 @@ struct mm_struct {
struct kioctx *ioctx_list; struct kioctx *ioctx_list;
struct kioctx default_kioctx; struct kioctx default_kioctx;
unsigned long hiwater_rss; /* High-water RSS usage */
unsigned long hiwater_vm; /* High-water virtual memory usage */
}; };
struct sighand_struct { struct sighand_struct {
...@@ -662,6 +665,11 @@ struct task_struct { ...@@ -662,6 +665,11 @@ struct task_struct {
wait_queue_t *io_wait; wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */ /* i/o counters(bytes read/written, #syscalls */
u64 rchar, wchar, syscr, syscw; 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 #ifdef CONFIG_NUMA
struct mempolicy *mempolicy; struct mempolicy *mempolicy;
short il_next; /* could be shared with used_math */ short il_next; /* could be shared with used_math */
......
...@@ -528,3 +528,34 @@ void acct_process(long exitcode) ...@@ -528,3 +528,34 @@ void acct_process(long exitcode)
do_acct_process(exitcode, file); do_acct_process(exitcode, file);
fput(file); fput(file);
} }
/*
* acct_update_integrals
* - update mm integral fields in task_struct
*/
void acct_update_integrals(void)
{
struct task_struct *tsk = current;
if (likely(tsk->mm)) {
long delta = tsk->stime - tsk->acct_stimexpd;
tsk->acct_stimexpd = tsk->stime;
tsk->acct_rss_mem1 += delta * tsk->mm->rss;
tsk->acct_vm_mem1 += delta * tsk->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;
}
}
...@@ -806,6 +806,8 @@ fastcall NORET_TYPE void do_exit(long code) ...@@ -806,6 +806,8 @@ fastcall NORET_TYPE void do_exit(long code)
ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP); ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
} }
acct_update_integrals();
update_mem_hiwater();
group_dead = atomic_dec_and_test(&tsk->signal->live); group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) if (group_dead)
acct_process(code); acct_process(code);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/rmap.h> #include <linux/rmap.h>
#include <linux/acct.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -469,6 +470,9 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) ...@@ -469,6 +470,9 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
if (retval) if (retval)
goto free_pt; goto free_pt;
mm->hiwater_rss = mm->rss;
mm->hiwater_vm = mm->total_vm;
good_mm: good_mm:
tsk->mm = mm; tsk->mm = mm;
tsk->active_mm = mm; tsk->active_mm = mm;
...@@ -880,6 +884,8 @@ static task_t *copy_process(unsigned long clone_flags, ...@@ -880,6 +884,8 @@ static task_t *copy_process(unsigned long clone_flags,
p->wchar = 0; /* I/O counter: bytes written */ p->wchar = 0; /* I/O counter: bytes written */
p->syscr = 0; /* I/O counter: read syscalls */ p->syscr = 0; /* I/O counter: read syscalls */
p->syscw = 0; /* I/O counter: write syscalls */ p->syscw = 0; /* I/O counter: write syscalls */
acct_clear_integrals(p);
p->lock_depth = -1; /* -1 = no lock */ p->lock_depth = -1; /* -1 = no lock */
do_posix_clock_monotonic_gettime(&p->start_time); do_posix_clock_monotonic_gettime(&p->start_time);
p->security = NULL; p->security = NULL;
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/rmap.h> #include <linux/rmap.h>
#include <linux/acct.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -738,6 +739,7 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long address, ...@@ -738,6 +739,7 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long address,
tlb = tlb_gather_mmu(mm, 0); tlb = tlb_gather_mmu(mm, 0);
unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details); unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
tlb_finish_mmu(tlb, address, end); tlb_finish_mmu(tlb, address, end);
acct_update_integrals();
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
} }
...@@ -1316,9 +1318,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, ...@@ -1316,9 +1318,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
if (likely(pte_same(*page_table, pte))) { if (likely(pte_same(*page_table, pte))) {
if (PageAnon(old_page)) if (PageAnon(old_page))
mm->anon_rss--; mm->anon_rss--;
if (PageReserved(old_page)) if (PageReserved(old_page)) {
++mm->rss; ++mm->rss;
else acct_update_integrals();
update_mem_hiwater();
} else
page_remove_rmap(old_page); page_remove_rmap(old_page);
break_cow(vma, new_page, address, page_table); break_cow(vma, new_page, address, page_table);
lru_cache_add_active(new_page); lru_cache_add_active(new_page);
...@@ -1600,6 +1604,9 @@ static int do_swap_page(struct mm_struct * mm, ...@@ -1600,6 +1604,9 @@ static int do_swap_page(struct mm_struct * mm,
remove_exclusive_swap_page(page); remove_exclusive_swap_page(page);
mm->rss++; mm->rss++;
acct_update_integrals();
update_mem_hiwater();
pte = mk_pte(page, vma->vm_page_prot); pte = mk_pte(page, vma->vm_page_prot);
if (write_access && can_share_swap_page(page)) { if (write_access && can_share_swap_page(page)) {
pte = maybe_mkwrite(pte_mkdirty(pte), vma); pte = maybe_mkwrite(pte_mkdirty(pte), vma);
...@@ -1665,6 +1672,8 @@ do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -1665,6 +1672,8 @@ do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
goto out; goto out;
} }
mm->rss++; mm->rss++;
acct_update_integrals();
update_mem_hiwater();
entry = maybe_mkwrite(pte_mkdirty(mk_pte(page, entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
vma->vm_page_prot)), vma->vm_page_prot)),
vma); vma);
...@@ -1774,6 +1783,9 @@ do_no_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -1774,6 +1783,9 @@ do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (pte_none(*page_table)) { if (pte_none(*page_table)) {
if (!PageReserved(new_page)) if (!PageReserved(new_page))
++mm->rss; ++mm->rss;
acct_update_integrals();
update_mem_hiwater();
flush_icache_page(vma, new_page); flush_icache_page(vma, new_page);
entry = mk_pte(new_page, vma->vm_page_prot); entry = mk_pte(new_page, vma->vm_page_prot);
if (write_access) if (write_access)
...@@ -2092,6 +2104,22 @@ unsigned long vmalloc_to_pfn(void * vmalloc_addr) ...@@ -2092,6 +2104,22 @@ unsigned long vmalloc_to_pfn(void * vmalloc_addr)
EXPORT_SYMBOL(vmalloc_to_pfn); 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 *tsk = current;
if (tsk->mm) {
if (tsk->mm->hiwater_rss < tsk->mm->rss)
tsk->mm->hiwater_rss = tsk->mm->rss;
if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
tsk->mm->hiwater_vm = tsk->mm->total_vm;
}
}
#if !defined(__HAVE_ARCH_GATE_AREA) #if !defined(__HAVE_ARCH_GATE_AREA)
#if defined(AT_SYSINFO_EHDR) #if defined(AT_SYSINFO_EHDR)
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h>
#include <linux/shm.h> #include <linux/shm.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/acct.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/mempolicy.h> #include <linux/mempolicy.h>
#include <linux/rmap.h> #include <linux/rmap.h>
...@@ -1019,6 +1021,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -1019,6 +1021,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
pgoff, flags & MAP_NONBLOCK); pgoff, flags & MAP_NONBLOCK);
down_write(&mm->mmap_sem); down_write(&mm->mmap_sem);
} }
acct_update_integrals();
update_mem_hiwater();
return addr; return addr;
unmap_and_free_vma: unmap_and_free_vma:
...@@ -1365,6 +1369,8 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address) ...@@ -1365,6 +1369,8 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
if (vma->vm_flags & VM_LOCKED) if (vma->vm_flags & VM_LOCKED)
vma->vm_mm->locked_vm += grow; vma->vm_mm->locked_vm += grow;
__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow); __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
acct_update_integrals();
update_mem_hiwater();
anon_vma_unlock(vma); anon_vma_unlock(vma);
return 0; return 0;
} }
...@@ -1428,6 +1434,8 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address) ...@@ -1428,6 +1434,8 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address)
if (vma->vm_flags & VM_LOCKED) if (vma->vm_flags & VM_LOCKED)
vma->vm_mm->locked_vm += grow; vma->vm_mm->locked_vm += grow;
__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow); __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
acct_update_integrals();
update_mem_hiwater();
anon_vma_unlock(vma); anon_vma_unlock(vma);
return 0; return 0;
} }
...@@ -1815,6 +1823,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len) ...@@ -1815,6 +1823,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
mm->locked_vm += len >> PAGE_SHIFT; mm->locked_vm += len >> PAGE_SHIFT;
make_pages_present(addr, addr + len); make_pages_present(addr, addr + len);
} }
acct_update_integrals();
update_mem_hiwater();
return addr; return addr;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/acct.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -250,6 +251,9 @@ static unsigned long move_vma(struct vm_area_struct *vma, ...@@ -250,6 +251,9 @@ static unsigned long move_vma(struct vm_area_struct *vma,
new_addr + new_len); new_addr + new_len);
} }
acct_update_integrals();
update_mem_hiwater();
return new_addr; return new_addr;
} }
...@@ -386,6 +390,8 @@ unsigned long do_mremap(unsigned long addr, ...@@ -386,6 +390,8 @@ unsigned long do_mremap(unsigned long addr,
make_pages_present(addr + old_len, make_pages_present(addr + old_len,
addr + new_len); addr + new_len);
} }
acct_update_integrals();
update_mem_hiwater();
ret = addr; ret = addr;
goto out; goto out;
} }
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <linux/swapops.h> #include <linux/swapops.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acct.h>
#include <linux/rmap.h> #include <linux/rmap.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
...@@ -606,6 +607,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) ...@@ -606,6 +607,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
} }
mm->rss--; mm->rss--;
acct_update_integrals();
page_remove_rmap(page); page_remove_rmap(page);
page_cache_release(page); page_cache_release(page);
...@@ -710,6 +712,7 @@ static void try_to_unmap_cluster(unsigned long cursor, ...@@ -710,6 +712,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
page_remove_rmap(page); page_remove_rmap(page);
page_cache_release(page); page_cache_release(page);
acct_update_integrals();
mm->rss--; mm->rss--;
(*mapcount)--; (*mapcount)--;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/rmap.h> #include <linux/rmap.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/acct.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
...@@ -436,6 +437,8 @@ unuse_pte(struct vm_area_struct *vma, unsigned long address, pte_t *dir, ...@@ -436,6 +437,8 @@ unuse_pte(struct vm_area_struct *vma, unsigned long address, pte_t *dir,
set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot))); set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
page_add_anon_rmap(page, vma, address); page_add_anon_rmap(page, vma, address);
swap_free(entry); swap_free(entry);
acct_update_integrals();
update_mem_hiwater();
} }
/* vma->vm_mm->page_table_lock is held */ /* vma->vm_mm->page_table_lock is held */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment