aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/proc.txt5
-rw-r--r--fs/proc/task_mmu.c51
2 files changed, 55 insertions, 1 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 9f13b6e28676..fdeb5b33349f 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -460,7 +460,10 @@ and a page is modified, the file page is replaced by a private anonymous copy.
460hugetlbfs page which is *not* counted in "RSS" or "PSS" field for historical 460hugetlbfs page which is *not* counted in "RSS" or "PSS" field for historical
461reasons. And these are not included in {Shared,Private}_{Clean,Dirty} field. 461reasons. And these are not included in {Shared,Private}_{Clean,Dirty} field.
462"Swap" shows how much would-be-anonymous memory is also used, but out on swap. 462"Swap" shows how much would-be-anonymous memory is also used, but out on swap.
463"SwapPss" shows proportional swap share of this mapping. 463For shmem mappings, "Swap" includes also the size of the mapped (and not
464replaced by copy-on-write) part of the underlying shmem object out on swap.
465"SwapPss" shows proportional swap share of this mapping. Unlike "Swap", this
466does not take into account swapped out page of underlying shmem objects.
464"Locked" indicates whether the mapping is locked in memory or not. 467"Locked" indicates whether the mapping is locked in memory or not.
465 468
466"VmFlags" field deserves a separate description. This member represents the kernel 469"VmFlags" field deserves a separate description. This member represents the kernel
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 187b3b5f242e..85ef60fdf2c0 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -451,6 +451,7 @@ struct mem_size_stats {
451 unsigned long private_hugetlb; 451 unsigned long private_hugetlb;
452 u64 pss; 452 u64 pss;
453 u64 swap_pss; 453 u64 swap_pss;
454 bool check_shmem_swap;
454}; 455};
455 456
456static void smaps_account(struct mem_size_stats *mss, struct page *page, 457static void smaps_account(struct mem_size_stats *mss, struct page *page,
@@ -485,6 +486,45 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
485 } 486 }
486} 487}
487 488
489#ifdef CONFIG_SHMEM
490static unsigned long smaps_shmem_swap(struct vm_area_struct *vma,
491 unsigned long addr)
492{
493 struct page *page;
494
495 page = find_get_entry(vma->vm_file->f_mapping,
496 linear_page_index(vma, addr));
497 if (!page)
498 return 0;
499
500 if (radix_tree_exceptional_entry(page))
501 return PAGE_SIZE;
502
503 page_cache_release(page);
504 return 0;
505
506}
507
508static int smaps_pte_hole(unsigned long addr, unsigned long end,
509 struct mm_walk *walk)
510{
511 struct mem_size_stats *mss = walk->private;
512
513 while (addr < end) {
514 mss->swap += smaps_shmem_swap(walk->vma, addr);
515 addr += PAGE_SIZE;
516 }
517
518 return 0;
519}
520#else
521static unsigned long smaps_shmem_swap(struct vm_area_struct *vma,
522 unsigned long addr)
523{
524 return 0;
525}
526#endif
527
488static void smaps_pte_entry(pte_t *pte, unsigned long addr, 528static void smaps_pte_entry(pte_t *pte, unsigned long addr,
489 struct mm_walk *walk) 529 struct mm_walk *walk)
490{ 530{
@@ -512,6 +552,9 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
512 } 552 }
513 } else if (is_migration_entry(swpent)) 553 } else if (is_migration_entry(swpent))
514 page = migration_entry_to_page(swpent); 554 page = migration_entry_to_page(swpent);
555 } else if (unlikely(IS_ENABLED(CONFIG_SHMEM) && mss->check_shmem_swap
556 && pte_none(*pte))) {
557 mss->swap += smaps_shmem_swap(vma, addr);
515 } 558 }
516 559
517 if (!page) 560 if (!page)
@@ -671,6 +714,14 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
671 }; 714 };
672 715
673 memset(&mss, 0, sizeof mss); 716 memset(&mss, 0, sizeof mss);
717
718#ifdef CONFIG_SHMEM
719 if (vma->vm_file && shmem_mapping(vma->vm_file->f_mapping)) {
720 mss.check_shmem_swap = true;
721 smaps_walk.pte_hole = smaps_pte_hole;
722 }
723#endif
724
674 /* mmap_sem is held in m_start */ 725 /* mmap_sem is held in m_start */
675 walk_page_vma(vma, &smaps_walk); 726 walk_page_vma(vma, &smaps_walk);
676 727