aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2010-03-05 16:41:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-06 14:26:24 -0500
commitb084d4353ff99d824d3bc5a5c2c22c70b1fba722 (patch)
tree8178db2b337fc8a36e6ca2e1fc2e7d7473957e27
parent34e55232e59f7b19050267a05ff1226e5cd122a5 (diff)
mm: count swap usage
A frequent questions from users about memory management is what numbers of swap ents are user for processes. And this information will give some hints to oom-killer. Besides we can count the number of swapents per a process by scanning /proc/<pid>/smaps, this is very slow and not good for usual process information handler which works like 'ps' or 'top'. (ps or top is now enough slow..) This patch adds a counter of swapents to mm_counter and update is at each swap events. Information is exported via /proc/<pid>/status file as [kamezawa@bluextal memory]$ cat /proc/self/status Name: cat State: R (running) Tgid: 2910 Pid: 2910 PPid: 2823 TracerPid: 0 Uid: 500 500 500 500 Gid: 500 500 500 500 FDSize: 256 Groups: 500 VmPeak: 82696 kB VmSize: 82696 kB VmLck: 0 kB VmHWM: 432 kB VmRSS: 432 kB VmData: 172 kB VmStk: 84 kB VmExe: 48 kB VmLib: 1568 kB VmPTE: 40 kB VmSwap: 0 kB <=============== this. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Reviewed-by: Christoph Lameter <cl@linux-foundation.org> Cc: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/filesystems/proc.txt2
-rw-r--r--fs/proc/task_mmu.c9
-rw-r--r--include/linux/mm_types.h1
-rw-r--r--mm/memory.c16
-rw-r--r--mm/rmap.c1
-rw-r--r--mm/swapfile.c1
6 files changed, 23 insertions, 7 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index e418f3d8f427..b5c5fc657a88 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -164,6 +164,7 @@ read the file /proc/PID/status:
164 VmExe: 68 kB 164 VmExe: 68 kB
165 VmLib: 1412 kB 165 VmLib: 1412 kB
166 VmPTE: 20 kb 166 VmPTE: 20 kb
167 VmSwap: 0 kB
167 Threads: 1 168 Threads: 1
168 SigQ: 0/28578 169 SigQ: 0/28578
169 SigPnd: 0000000000000000 170 SigPnd: 0000000000000000
@@ -219,6 +220,7 @@ Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
219 VmExe size of text segment 220 VmExe size of text segment
220 VmLib size of shared library code 221 VmLib size of shared library code
221 VmPTE size of page table entries 222 VmPTE size of page table entries
223 VmSwap size of swap usage (the number of referred swapents)
222 Threads number of threads 224 Threads number of threads
223 SigQ number of signals queued/max. number for queue 225 SigQ number of signals queued/max. number for queue
224 SigPnd bitmap of pending signals for the thread 226 SigPnd bitmap of pending signals for the thread
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 375581276011..183f8ff5f400 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -16,7 +16,7 @@
16 16
17void task_mem(struct seq_file *m, struct mm_struct *mm) 17void task_mem(struct seq_file *m, struct mm_struct *mm)
18{ 18{
19 unsigned long data, text, lib; 19 unsigned long data, text, lib, swap;
20 unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss; 20 unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
21 21
22 /* 22 /*
@@ -36,6 +36,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
36 data = mm->total_vm - mm->shared_vm - mm->stack_vm; 36 data = mm->total_vm - mm->shared_vm - mm->stack_vm;
37 text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10; 37 text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
38 lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text; 38 lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
39 swap = get_mm_counter(mm, MM_SWAPENTS);
39 seq_printf(m, 40 seq_printf(m,
40 "VmPeak:\t%8lu kB\n" 41 "VmPeak:\t%8lu kB\n"
41 "VmSize:\t%8lu kB\n" 42 "VmSize:\t%8lu kB\n"
@@ -46,7 +47,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
46 "VmStk:\t%8lu kB\n" 47 "VmStk:\t%8lu kB\n"
47 "VmExe:\t%8lu kB\n" 48 "VmExe:\t%8lu kB\n"
48 "VmLib:\t%8lu kB\n" 49 "VmLib:\t%8lu kB\n"
49 "VmPTE:\t%8lu kB\n", 50 "VmPTE:\t%8lu kB\n"
51 "VmSwap:\t%8lu kB\n",
50 hiwater_vm << (PAGE_SHIFT-10), 52 hiwater_vm << (PAGE_SHIFT-10),
51 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10), 53 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
52 mm->locked_vm << (PAGE_SHIFT-10), 54 mm->locked_vm << (PAGE_SHIFT-10),
@@ -54,7 +56,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
54 total_rss << (PAGE_SHIFT-10), 56 total_rss << (PAGE_SHIFT-10),
55 data << (PAGE_SHIFT-10), 57 data << (PAGE_SHIFT-10),
56 mm->stack_vm << (PAGE_SHIFT-10), text, lib, 58 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
57 (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10); 59 (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
60 swap << (PAGE_SHIFT-10));
58} 61}
59 62
60unsigned long task_vsize(struct mm_struct *mm) 63unsigned long task_vsize(struct mm_struct *mm)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 21861239ab0c..19549d7275ab 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -198,6 +198,7 @@ struct core_state {
198enum { 198enum {
199 MM_FILEPAGES, 199 MM_FILEPAGES,
200 MM_ANONPAGES, 200 MM_ANONPAGES,
201 MM_SWAPENTS,
201 NR_MM_COUNTERS 202 NR_MM_COUNTERS
202}; 203};
203 204
diff --git a/mm/memory.c b/mm/memory.c
index a4597614f18d..77d9f840936b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -679,7 +679,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
679 &src_mm->mmlist); 679 &src_mm->mmlist);
680 spin_unlock(&mmlist_lock); 680 spin_unlock(&mmlist_lock);
681 } 681 }
682 if (is_write_migration_entry(entry) && 682 if (likely(!non_swap_entry(entry)))
683 rss[MM_SWAPENTS]++;
684 else if (is_write_migration_entry(entry) &&
683 is_cow_mapping(vm_flags)) { 685 is_cow_mapping(vm_flags)) {
684 /* 686 /*
685 * COW mappings require pages in both parent 687 * COW mappings require pages in both parent
@@ -974,9 +976,14 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
974 if (pte_file(ptent)) { 976 if (pte_file(ptent)) {
975 if (unlikely(!(vma->vm_flags & VM_NONLINEAR))) 977 if (unlikely(!(vma->vm_flags & VM_NONLINEAR)))
976 print_bad_pte(vma, addr, ptent, NULL); 978 print_bad_pte(vma, addr, ptent, NULL);
977 } else if 979 } else {
978 (unlikely(!free_swap_and_cache(pte_to_swp_entry(ptent)))) 980 swp_entry_t entry = pte_to_swp_entry(ptent);
979 print_bad_pte(vma, addr, ptent, NULL); 981
982 if (!non_swap_entry(entry))
983 rss[MM_SWAPENTS]--;
984 if (unlikely(!free_swap_and_cache(entry)))
985 print_bad_pte(vma, addr, ptent, NULL);
986 }
980 pte_clear_not_present_full(mm, addr, pte, tlb->fullmm); 987 pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
981 } while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0)); 988 } while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0));
982 989
@@ -2692,6 +2699,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
2692 */ 2699 */
2693 2700
2694 inc_mm_counter_fast(mm, MM_ANONPAGES); 2701 inc_mm_counter_fast(mm, MM_ANONPAGES);
2702 dec_mm_counter_fast(mm, MM_SWAPENTS);
2695 pte = mk_pte(page, vma->vm_page_prot); 2703 pte = mk_pte(page, vma->vm_page_prot);
2696 if ((flags & FAULT_FLAG_WRITE) && reuse_swap_page(page)) { 2704 if ((flags & FAULT_FLAG_WRITE) && reuse_swap_page(page)) {
2697 pte = maybe_mkwrite(pte_mkdirty(pte), vma); 2705 pte = maybe_mkwrite(pte_mkdirty(pte), vma);
diff --git a/mm/rmap.c b/mm/rmap.c
index 73d0472884c2..5cb47111f79e 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -840,6 +840,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
840 spin_unlock(&mmlist_lock); 840 spin_unlock(&mmlist_lock);
841 } 841 }
842 dec_mm_counter(mm, MM_ANONPAGES); 842 dec_mm_counter(mm, MM_ANONPAGES);
843 inc_mm_counter(mm, MM_SWAPENTS);
843 } else if (PAGE_MIGRATION) { 844 } else if (PAGE_MIGRATION) {
844 /* 845 /*
845 * Store the pfn of the page in a special migration 846 * Store the pfn of the page in a special migration
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 893984946a2c..187a21f8b7bd 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -840,6 +840,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
840 goto out; 840 goto out;
841 } 841 }
842 842
843 dec_mm_counter(vma->vm_mm, MM_SWAPENTS);
843 inc_mm_counter(vma->vm_mm, MM_ANONPAGES); 844 inc_mm_counter(vma->vm_mm, MM_ANONPAGES);
844 get_page(page); 845 get_page(page);
845 set_pte_at(vma->vm_mm, addr, pte, 846 set_pte_at(vma->vm_mm, addr, pte,