aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/task_mmu.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/proc/task_mmu.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/proc/task_mmu.c')
-rw-r--r--fs/proc/task_mmu.c393
1 files changed, 321 insertions, 72 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 1dbca4e8cc16..25b6a887adb9 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1,5 +1,6 @@
1#include <linux/mm.h> 1#include <linux/mm.h>
2#include <linux/hugetlb.h> 2#include <linux/hugetlb.h>
3#include <linux/huge_mm.h>
3#include <linux/mount.h> 4#include <linux/mount.h>
4#include <linux/seq_file.h> 5#include <linux/seq_file.h>
5#include <linux/highmem.h> 6#include <linux/highmem.h>
@@ -7,6 +8,7 @@
7#include <linux/slab.h> 8#include <linux/slab.h>
8#include <linux/pagemap.h> 9#include <linux/pagemap.h>
9#include <linux/mempolicy.h> 10#include <linux/mempolicy.h>
11#include <linux/rmap.h>
10#include <linux/swap.h> 12#include <linux/swap.h>
11#include <linux/swapops.h> 13#include <linux/swapops.h>
12 14
@@ -66,8 +68,9 @@ unsigned long task_vsize(struct mm_struct *mm)
66 return PAGE_SIZE * mm->total_vm; 68 return PAGE_SIZE * mm->total_vm;
67} 69}
68 70
69int task_statm(struct mm_struct *mm, int *shared, int *text, 71unsigned long task_statm(struct mm_struct *mm,
70 int *data, int *resident) 72 unsigned long *shared, unsigned long *text,
73 unsigned long *data, unsigned long *resident)
71{ 74{
72 *shared = get_mm_counter(mm, MM_FILEPAGES); 75 *shared = get_mm_counter(mm, MM_FILEPAGES);
73 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) 76 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
@@ -118,14 +121,14 @@ static void *m_start(struct seq_file *m, loff_t *pos)
118 121
119 priv->task = get_pid_task(priv->pid, PIDTYPE_PID); 122 priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
120 if (!priv->task) 123 if (!priv->task)
121 return NULL; 124 return ERR_PTR(-ESRCH);
122 125
123 mm = mm_for_maps(priv->task); 126 mm = mm_for_maps(priv->task);
124 if (!mm) 127 if (!mm || IS_ERR(mm))
125 return NULL; 128 return mm;
126 down_read(&mm->mmap_sem); 129 down_read(&mm->mmap_sem);
127 130
128 tail_vma = get_gate_vma(priv->task); 131 tail_vma = get_gate_vma(priv->task->mm);
129 priv->tail_vma = tail_vma; 132 priv->tail_vma = tail_vma;
130 133
131 /* Start with last addr hint */ 134 /* Start with last addr hint */
@@ -179,7 +182,8 @@ static void m_stop(struct seq_file *m, void *v)
179 struct proc_maps_private *priv = m->private; 182 struct proc_maps_private *priv = m->private;
180 struct vm_area_struct *vma = v; 183 struct vm_area_struct *vma = v;
181 184
182 vma_stop(priv, vma); 185 if (!IS_ERR(vma))
186 vma_stop(priv, vma);
183 if (priv->task) 187 if (priv->task)
184 put_task_struct(priv->task); 188 put_task_struct(priv->task);
185} 189}
@@ -207,10 +211,10 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
207{ 211{
208 struct mm_struct *mm = vma->vm_mm; 212 struct mm_struct *mm = vma->vm_mm;
209 struct file *file = vma->vm_file; 213 struct file *file = vma->vm_file;
210 int flags = vma->vm_flags; 214 vm_flags_t flags = vma->vm_flags;
211 unsigned long ino = 0; 215 unsigned long ino = 0;
212 unsigned long long pgoff = 0; 216 unsigned long long pgoff = 0;
213 unsigned long start; 217 unsigned long start, end;
214 dev_t dev = 0; 218 dev_t dev = 0;
215 int len; 219 int len;
216 220
@@ -223,13 +227,15 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
223 227
224 /* We don't show the stack guard page in /proc/maps */ 228 /* We don't show the stack guard page in /proc/maps */
225 start = vma->vm_start; 229 start = vma->vm_start;
226 if (vma->vm_flags & VM_GROWSDOWN) 230 if (stack_guard_page_start(vma, start))
227 if (!vma_stack_continue(vma->vm_prev, vma->vm_start)) 231 start += PAGE_SIZE;
228 start += PAGE_SIZE; 232 end = vma->vm_end;
233 if (stack_guard_page_end(vma, end))
234 end -= PAGE_SIZE;
229 235
230 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", 236 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
231 start, 237 start,
232 vma->vm_end, 238 end,
233 flags & VM_READ ? 'r' : '-', 239 flags & VM_READ ? 'r' : '-',
234 flags & VM_WRITE ? 'w' : '-', 240 flags & VM_WRITE ? 'w' : '-',
235 flags & VM_EXEC ? 'x' : '-', 241 flags & VM_EXEC ? 'x' : '-',
@@ -248,8 +254,8 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
248 const char *name = arch_vma_name(vma); 254 const char *name = arch_vma_name(vma);
249 if (!name) { 255 if (!name) {
250 if (mm) { 256 if (mm) {
251 if (vma->vm_start <= mm->start_brk && 257 if (vma->vm_start <= mm->brk &&
252 vma->vm_end >= mm->brk) { 258 vma->vm_end >= mm->start_brk) {
253 name = "[heap]"; 259 name = "[heap]";
254 } else if (vma->vm_start <= mm->start_stack && 260 } else if (vma->vm_start <= mm->start_stack &&
255 vma->vm_end >= mm->start_stack) { 261 vma->vm_end >= mm->start_stack) {
@@ -276,7 +282,8 @@ static int show_map(struct seq_file *m, void *v)
276 show_map_vma(m, vma); 282 show_map_vma(m, vma);
277 283
278 if (m->count < m->size) /* vma is copied successfully */ 284 if (m->count < m->size) /* vma is copied successfully */
279 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0; 285 m->version = (vma != get_gate_vma(task->mm))
286 ? vma->vm_start : 0;
280 return 0; 287 return 0;
281} 288}
282 289
@@ -327,55 +334,87 @@ struct mem_size_stats {
327 unsigned long private_clean; 334 unsigned long private_clean;
328 unsigned long private_dirty; 335 unsigned long private_dirty;
329 unsigned long referenced; 336 unsigned long referenced;
337 unsigned long anonymous;
338 unsigned long anonymous_thp;
330 unsigned long swap; 339 unsigned long swap;
331 u64 pss; 340 u64 pss;
332}; 341};
333 342
334static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, 343
335 struct mm_walk *walk) 344static void smaps_pte_entry(pte_t ptent, unsigned long addr,
345 unsigned long ptent_size, struct mm_walk *walk)
336{ 346{
337 struct mem_size_stats *mss = walk->private; 347 struct mem_size_stats *mss = walk->private;
338 struct vm_area_struct *vma = mss->vma; 348 struct vm_area_struct *vma = mss->vma;
339 pte_t *pte, ptent;
340 spinlock_t *ptl;
341 struct page *page; 349 struct page *page;
342 int mapcount; 350 int mapcount;
343 351
344 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); 352 if (is_swap_pte(ptent)) {
345 for (; addr != end; pte++, addr += PAGE_SIZE) { 353 mss->swap += ptent_size;
346 ptent = *pte; 354 return;
347 355 }
348 if (is_swap_pte(ptent)) {
349 mss->swap += PAGE_SIZE;
350 continue;
351 }
352 356
353 if (!pte_present(ptent)) 357 if (!pte_present(ptent))
354 continue; 358 return;
359
360 page = vm_normal_page(vma, addr, ptent);
361 if (!page)
362 return;
363
364 if (PageAnon(page))
365 mss->anonymous += ptent_size;
366
367 mss->resident += ptent_size;
368 /* Accumulate the size in pages that have been accessed. */
369 if (pte_young(ptent) || PageReferenced(page))
370 mss->referenced += ptent_size;
371 mapcount = page_mapcount(page);
372 if (mapcount >= 2) {
373 if (pte_dirty(ptent) || PageDirty(page))
374 mss->shared_dirty += ptent_size;
375 else
376 mss->shared_clean += ptent_size;
377 mss->pss += (ptent_size << PSS_SHIFT) / mapcount;
378 } else {
379 if (pte_dirty(ptent) || PageDirty(page))
380 mss->private_dirty += ptent_size;
381 else
382 mss->private_clean += ptent_size;
383 mss->pss += (ptent_size << PSS_SHIFT);
384 }
385}
355 386
356 page = vm_normal_page(vma, addr, ptent); 387static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
357 if (!page) 388 struct mm_walk *walk)
358 continue; 389{
390 struct mem_size_stats *mss = walk->private;
391 struct vm_area_struct *vma = mss->vma;
392 pte_t *pte;
393 spinlock_t *ptl;
359 394
360 mss->resident += PAGE_SIZE; 395 spin_lock(&walk->mm->page_table_lock);
361 /* Accumulate the size in pages that have been accessed. */ 396 if (pmd_trans_huge(*pmd)) {
362 if (pte_young(ptent) || PageReferenced(page)) 397 if (pmd_trans_splitting(*pmd)) {
363 mss->referenced += PAGE_SIZE; 398 spin_unlock(&walk->mm->page_table_lock);
364 mapcount = page_mapcount(page); 399 wait_split_huge_page(vma->anon_vma, pmd);
365 if (mapcount >= 2) {
366 if (pte_dirty(ptent) || PageDirty(page))
367 mss->shared_dirty += PAGE_SIZE;
368 else
369 mss->shared_clean += PAGE_SIZE;
370 mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
371 } else { 400 } else {
372 if (pte_dirty(ptent) || PageDirty(page)) 401 smaps_pte_entry(*(pte_t *)pmd, addr,
373 mss->private_dirty += PAGE_SIZE; 402 HPAGE_PMD_SIZE, walk);
374 else 403 spin_unlock(&walk->mm->page_table_lock);
375 mss->private_clean += PAGE_SIZE; 404 mss->anonymous_thp += HPAGE_PMD_SIZE;
376 mss->pss += (PAGE_SIZE << PSS_SHIFT); 405 return 0;
377 } 406 }
407 } else {
408 spin_unlock(&walk->mm->page_table_lock);
378 } 409 }
410 /*
411 * The mmap_sem held all the way back in m_start() is what
412 * keeps khugepaged out of here and from collapsing things
413 * in here.
414 */
415 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
416 for (; addr != end; pte++, addr += PAGE_SIZE)
417 smaps_pte_entry(*pte, addr, PAGE_SIZE, walk);
379 pte_unmap_unlock(pte - 1, ptl); 418 pte_unmap_unlock(pte - 1, ptl);
380 cond_resched(); 419 cond_resched();
381 return 0; 420 return 0;
@@ -410,9 +449,12 @@ static int show_smap(struct seq_file *m, void *v)
410 "Private_Clean: %8lu kB\n" 449 "Private_Clean: %8lu kB\n"
411 "Private_Dirty: %8lu kB\n" 450 "Private_Dirty: %8lu kB\n"
412 "Referenced: %8lu kB\n" 451 "Referenced: %8lu kB\n"
452 "Anonymous: %8lu kB\n"
453 "AnonHugePages: %8lu kB\n"
413 "Swap: %8lu kB\n" 454 "Swap: %8lu kB\n"
414 "KernelPageSize: %8lu kB\n" 455 "KernelPageSize: %8lu kB\n"
415 "MMUPageSize: %8lu kB\n", 456 "MMUPageSize: %8lu kB\n"
457 "Locked: %8lu kB\n",
416 (vma->vm_end - vma->vm_start) >> 10, 458 (vma->vm_end - vma->vm_start) >> 10,
417 mss.resident >> 10, 459 mss.resident >> 10,
418 (unsigned long)(mss.pss >> (10 + PSS_SHIFT)), 460 (unsigned long)(mss.pss >> (10 + PSS_SHIFT)),
@@ -421,12 +463,17 @@ static int show_smap(struct seq_file *m, void *v)
421 mss.private_clean >> 10, 463 mss.private_clean >> 10,
422 mss.private_dirty >> 10, 464 mss.private_dirty >> 10,
423 mss.referenced >> 10, 465 mss.referenced >> 10,
466 mss.anonymous >> 10,
467 mss.anonymous_thp >> 10,
424 mss.swap >> 10, 468 mss.swap >> 10,
425 vma_kernel_pagesize(vma) >> 10, 469 vma_kernel_pagesize(vma) >> 10,
426 vma_mmu_pagesize(vma) >> 10); 470 vma_mmu_pagesize(vma) >> 10,
471 (vma->vm_flags & VM_LOCKED) ?
472 (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0);
427 473
428 if (m->count < m->size) /* vma is copied successfully */ 474 if (m->count < m->size) /* vma is copied successfully */
429 m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0; 475 m->version = (vma != get_gate_vma(task->mm))
476 ? vma->vm_start : 0;
430 return 0; 477 return 0;
431} 478}
432 479
@@ -457,6 +504,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
457 spinlock_t *ptl; 504 spinlock_t *ptl;
458 struct page *page; 505 struct page *page;
459 506
507 split_huge_page_pmd(walk->mm, pmd);
508
460 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); 509 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
461 for (; addr != end; pte++, addr += PAGE_SIZE) { 510 for (; addr != end; pte++, addr += PAGE_SIZE) {
462 ptent = *pte; 511 ptent = *pte;
@@ -487,15 +536,17 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
487 char buffer[PROC_NUMBUF]; 536 char buffer[PROC_NUMBUF];
488 struct mm_struct *mm; 537 struct mm_struct *mm;
489 struct vm_area_struct *vma; 538 struct vm_area_struct *vma;
490 long type; 539 int type;
540 int rv;
491 541
492 memset(buffer, 0, sizeof(buffer)); 542 memset(buffer, 0, sizeof(buffer));
493 if (count > sizeof(buffer) - 1) 543 if (count > sizeof(buffer) - 1)
494 count = sizeof(buffer) - 1; 544 count = sizeof(buffer) - 1;
495 if (copy_from_user(buffer, buf, count)) 545 if (copy_from_user(buffer, buf, count))
496 return -EFAULT; 546 return -EFAULT;
497 if (strict_strtol(strstrip(buffer), 10, &type)) 547 rv = kstrtoint(strstrip(buffer), 10, &type);
498 return -EINVAL; 548 if (rv < 0)
549 return rv;
499 if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED) 550 if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED)
500 return -EINVAL; 551 return -EINVAL;
501 task = get_proc_task(file->f_path.dentry->d_inode); 552 task = get_proc_task(file->f_path.dentry->d_inode);
@@ -539,6 +590,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
539 590
540const struct file_operations proc_clear_refs_operations = { 591const struct file_operations proc_clear_refs_operations = {
541 .write = clear_refs_write, 592 .write = clear_refs_write,
593 .llseek = noop_llseek,
542}; 594};
543 595
544struct pagemapread { 596struct pagemapread {
@@ -612,6 +664,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
612 pte_t *pte; 664 pte_t *pte;
613 int err = 0; 665 int err = 0;
614 666
667 split_huge_page_pmd(walk->mm, pmd);
668
615 /* find the first VMA at or above 'addr' */ 669 /* find the first VMA at or above 'addr' */
616 vma = find_vma(walk->mm, addr); 670 vma = find_vma(walk->mm, addr);
617 for (; addr != end; addr += PAGE_SIZE) { 671 for (; addr != end; addr += PAGE_SIZE) {
@@ -699,6 +753,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
699 * skip over unmapped regions. 753 * skip over unmapped regions.
700 */ 754 */
701#define PAGEMAP_WALK_SIZE (PMD_SIZE) 755#define PAGEMAP_WALK_SIZE (PMD_SIZE)
756#define PAGEMAP_WALK_MASK (PMD_MASK)
702static ssize_t pagemap_read(struct file *file, char __user *buf, 757static ssize_t pagemap_read(struct file *file, char __user *buf,
703 size_t count, loff_t *ppos) 758 size_t count, loff_t *ppos)
704{ 759{
@@ -716,29 +771,25 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
716 if (!task) 771 if (!task)
717 goto out; 772 goto out;
718 773
719 ret = -EACCES;
720 if (!ptrace_may_access(task, PTRACE_MODE_READ))
721 goto out_task;
722
723 ret = -EINVAL; 774 ret = -EINVAL;
724 /* file position must be aligned */ 775 /* file position must be aligned */
725 if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) 776 if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES))
726 goto out_task; 777 goto out_task;
727 778
728 ret = 0; 779 ret = 0;
729
730 if (!count) 780 if (!count)
731 goto out_task; 781 goto out_task;
732 782
733 mm = get_task_mm(task);
734 if (!mm)
735 goto out_task;
736
737 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); 783 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
738 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); 784 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
739 ret = -ENOMEM; 785 ret = -ENOMEM;
740 if (!pm.buffer) 786 if (!pm.buffer)
741 goto out_mm; 787 goto out_task;
788
789 mm = mm_for_maps(task);
790 ret = PTR_ERR(mm);
791 if (!mm || IS_ERR(mm))
792 goto out_free;
742 793
743 pagemap_walk.pmd_entry = pagemap_pte_range; 794 pagemap_walk.pmd_entry = pagemap_pte_range;
744 pagemap_walk.pte_hole = pagemap_pte_hole; 795 pagemap_walk.pte_hole = pagemap_pte_hole;
@@ -769,7 +820,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
769 unsigned long end; 820 unsigned long end;
770 821
771 pm.pos = 0; 822 pm.pos = 0;
772 end = start_vaddr + PAGEMAP_WALK_SIZE; 823 end = (start_vaddr + PAGEMAP_WALK_SIZE) & PAGEMAP_WALK_MASK;
773 /* overflow ? */ 824 /* overflow ? */
774 if (end < start_vaddr || end > end_vaddr) 825 if (end < start_vaddr || end > end_vaddr)
775 end = end_vaddr; 826 end = end_vaddr;
@@ -781,7 +832,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
781 len = min(count, PM_ENTRY_BYTES * pm.pos); 832 len = min(count, PM_ENTRY_BYTES * pm.pos);
782 if (copy_to_user(buf, pm.buffer, len)) { 833 if (copy_to_user(buf, pm.buffer, len)) {
783 ret = -EFAULT; 834 ret = -EFAULT;
784 goto out_free; 835 goto out_mm;
785 } 836 }
786 copied += len; 837 copied += len;
787 buf += len; 838 buf += len;
@@ -791,10 +842,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
791 if (!ret || ret == PM_END_OF_BUFFER) 842 if (!ret || ret == PM_END_OF_BUFFER)
792 ret = copied; 843 ret = copied;
793 844
794out_free:
795 kfree(pm.buffer);
796out_mm: 845out_mm:
797 mmput(mm); 846 mmput(mm);
847out_free:
848 kfree(pm.buffer);
798out_task: 849out_task:
799 put_task_struct(task); 850 put_task_struct(task);
800out: 851out:
@@ -808,7 +859,192 @@ const struct file_operations proc_pagemap_operations = {
808#endif /* CONFIG_PROC_PAGE_MONITOR */ 859#endif /* CONFIG_PROC_PAGE_MONITOR */
809 860
810#ifdef CONFIG_NUMA 861#ifdef CONFIG_NUMA
811extern int show_numa_map(struct seq_file *m, void *v); 862
863struct numa_maps {
864 struct vm_area_struct *vma;
865 unsigned long pages;
866 unsigned long anon;
867 unsigned long active;
868 unsigned long writeback;
869 unsigned long mapcount_max;
870 unsigned long dirty;
871 unsigned long swapcache;
872 unsigned long node[MAX_NUMNODES];
873};
874
875struct numa_maps_private {
876 struct proc_maps_private proc_maps;
877 struct numa_maps md;
878};
879
880static void gather_stats(struct page *page, struct numa_maps *md, int pte_dirty)
881{
882 int count = page_mapcount(page);
883
884 md->pages++;
885 if (pte_dirty || PageDirty(page))
886 md->dirty++;
887
888 if (PageSwapCache(page))
889 md->swapcache++;
890
891 if (PageActive(page) || PageUnevictable(page))
892 md->active++;
893
894 if (PageWriteback(page))
895 md->writeback++;
896
897 if (PageAnon(page))
898 md->anon++;
899
900 if (count > md->mapcount_max)
901 md->mapcount_max = count;
902
903 md->node[page_to_nid(page)]++;
904}
905
906static int gather_pte_stats(pmd_t *pmd, unsigned long addr,
907 unsigned long end, struct mm_walk *walk)
908{
909 struct numa_maps *md;
910 spinlock_t *ptl;
911 pte_t *orig_pte;
912 pte_t *pte;
913
914 md = walk->private;
915 orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
916 do {
917 struct page *page;
918 int nid;
919
920 if (!pte_present(*pte))
921 continue;
922
923 page = vm_normal_page(md->vma, addr, *pte);
924 if (!page)
925 continue;
926
927 if (PageReserved(page))
928 continue;
929
930 nid = page_to_nid(page);
931 if (!node_isset(nid, node_states[N_HIGH_MEMORY]))
932 continue;
933
934 gather_stats(page, md, pte_dirty(*pte));
935
936 } while (pte++, addr += PAGE_SIZE, addr != end);
937 pte_unmap_unlock(orig_pte, ptl);
938 return 0;
939}
940#ifdef CONFIG_HUGETLB_PAGE
941static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
942 unsigned long addr, unsigned long end, struct mm_walk *walk)
943{
944 struct numa_maps *md;
945 struct page *page;
946
947 if (pte_none(*pte))
948 return 0;
949
950 page = pte_page(*pte);
951 if (!page)
952 return 0;
953
954 md = walk->private;
955 gather_stats(page, md, pte_dirty(*pte));
956 return 0;
957}
958
959#else
960static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
961 unsigned long addr, unsigned long end, struct mm_walk *walk)
962{
963 return 0;
964}
965#endif
966
967/*
968 * Display pages allocated per node and memory policy via /proc.
969 */
970static int show_numa_map(struct seq_file *m, void *v)
971{
972 struct numa_maps_private *numa_priv = m->private;
973 struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
974 struct vm_area_struct *vma = v;
975 struct numa_maps *md = &numa_priv->md;
976 struct file *file = vma->vm_file;
977 struct mm_struct *mm = vma->vm_mm;
978 struct mm_walk walk = {};
979 struct mempolicy *pol;
980 int n;
981 char buffer[50];
982
983 if (!mm)
984 return 0;
985
986 /* Ensure we start with an empty set of numa_maps statistics. */
987 memset(md, 0, sizeof(*md));
988
989 md->vma = vma;
990
991 walk.hugetlb_entry = gather_hugetbl_stats;
992 walk.pmd_entry = gather_pte_stats;
993 walk.private = md;
994 walk.mm = mm;
995
996 pol = get_vma_policy(proc_priv->task, vma, vma->vm_start);
997 mpol_to_str(buffer, sizeof(buffer), pol, 0);
998 mpol_cond_put(pol);
999
1000 seq_printf(m, "%08lx %s", vma->vm_start, buffer);
1001
1002 if (file) {
1003 seq_printf(m, " file=");
1004 seq_path(m, &file->f_path, "\n\t= ");
1005 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
1006 seq_printf(m, " heap");
1007 } else if (vma->vm_start <= mm->start_stack &&
1008 vma->vm_end >= mm->start_stack) {
1009 seq_printf(m, " stack");
1010 }
1011
1012 walk_page_range(vma->vm_start, vma->vm_end, &walk);
1013
1014 if (!md->pages)
1015 goto out;
1016
1017 if (md->anon)
1018 seq_printf(m, " anon=%lu", md->anon);
1019
1020 if (md->dirty)
1021 seq_printf(m, " dirty=%lu", md->dirty);
1022
1023 if (md->pages != md->anon && md->pages != md->dirty)
1024 seq_printf(m, " mapped=%lu", md->pages);
1025
1026 if (md->mapcount_max > 1)
1027 seq_printf(m, " mapmax=%lu", md->mapcount_max);
1028
1029 if (md->swapcache)
1030 seq_printf(m, " swapcache=%lu", md->swapcache);
1031
1032 if (md->active < md->pages && !is_vm_hugetlb_page(vma))
1033 seq_printf(m, " active=%lu", md->active);
1034
1035 if (md->writeback)
1036 seq_printf(m, " writeback=%lu", md->writeback);
1037
1038 for_each_node_state(n, N_HIGH_MEMORY)
1039 if (md->node[n])
1040 seq_printf(m, " N%d=%lu", n, md->node[n]);
1041out:
1042 seq_putc(m, '\n');
1043
1044 if (m->count < m->size)
1045 m->version = (vma != proc_priv->tail_vma) ? vma->vm_start : 0;
1046 return 0;
1047}
812 1048
813static const struct seq_operations proc_pid_numa_maps_op = { 1049static const struct seq_operations proc_pid_numa_maps_op = {
814 .start = m_start, 1050 .start = m_start,
@@ -819,7 +1055,20 @@ static const struct seq_operations proc_pid_numa_maps_op = {
819 1055
820static int numa_maps_open(struct inode *inode, struct file *file) 1056static int numa_maps_open(struct inode *inode, struct file *file)
821{ 1057{
822 return do_maps_open(inode, file, &proc_pid_numa_maps_op); 1058 struct numa_maps_private *priv;
1059 int ret = -ENOMEM;
1060 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1061 if (priv) {
1062 priv->proc_maps.pid = proc_pid(inode);
1063 ret = seq_open(file, &proc_pid_numa_maps_op);
1064 if (!ret) {
1065 struct seq_file *m = file->private_data;
1066 m->private = priv;
1067 } else {
1068 kfree(priv);
1069 }
1070 }
1071 return ret;
823} 1072}
824 1073
825const struct file_operations proc_numa_maps_operations = { 1074const struct file_operations proc_numa_maps_operations = {
@@ -828,4 +1077,4 @@ const struct file_operations proc_numa_maps_operations = {
828 .llseek = seq_lseek, 1077 .llseek = seq_lseek,
829 .release = seq_release_private, 1078 .release = seq_release_private,
830}; 1079};
831#endif 1080#endif /* CONFIG_NUMA */