All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/5] mm, shmem: Enhance per-process accounting of shared memory
@ 2014-09-15 14:24 ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Changes since v1:
 - Add VmFile and VmAnon line to /proc/<pid>/status.
 - Split first patch: new accounting code on one side and and adding
 new fields to status on the other.
 - Remove ShmOther and ShmSwapCache from smaps and rename ShmOrphan to
 ShmNotMapped.
 - Drop fourth patch "mm, shmem: Add shmem swap memory accounting".
 - Minor implementation details.

I also tried again to come to a better way to account for shmem swap
pages, but my effort were again unsuccessful. Any suggestion is gladly
welcome.

There are several shortcomings with the accounting of shared memory
(sysV shm, shared anonymous mapping, mapping to a tmpfs file). The
values in /proc/<pid>/status and statm don't allow to distinguish
between shmem memory and a shared mapping to a regular file, even
though theirs implication on memory usage are quite different: at
reclaim, file mapping can be dropped or write back on disk while shmem
needs a place in swap. As for shmem pages that are swapped-out or in
swap cache, they aren't accounted at all.

This series addresses these issues by adding new fields to status and
smaps file in /proc/<pid>/. The accounting of resident shared memory is
made in the same way as it's currently done for resident memory and
general swap (a counter in mm_rss_stat), but this approach proved
impractical for paged-out shared memory (it would requires a rmap walk
each time a page is paged-in).

/proc/<pid>/smaps also lacks proper accounting of shared memory since
shmem subsystem hides all implementation detail to generic mm code.
This series adds the shmem_locate() function that returns the location
of a particular page (resident, in swap or swap cache). Called from
smaps code, it allows to show more detailled accounting of shmem
mappings in smaps.

Patch 1 adds a counter to keep track of resident shmem memory.
Patch 2 adds VmFile, VmAnon and VmShm lines to /proc/<pid>/status.
Patch 3 adds a function to allow generic code to know the physical
location of a shmem page.
Patch 4 adds simple helper function.
Patch 5 adds shmem specific fields to /proc/<pid>/smaps.

Thanks,
Jerome

Jerome Marchand (5):
  mm, shmem: Add shmem resident memory accounting
  mm, procfs: Display VmAnon, VmFile and VmShm in /proc/pid/status
  mm, shmem: Add shmem_locate function
  mm, shmem: Add shmem_vma() helper
  mm, shmem: Show location of non-resident shmem pages in smaps

 Documentation/filesystems/proc.txt | 16 +++++++++-
 arch/s390/mm/pgtable.c             |  5 +---
 fs/proc/task_mmu.c                 | 60 ++++++++++++++++++++++++++++++++++++--
 include/linux/mm.h                 | 10 +++++++
 include/linux/mm_types.h           |  7 +++--
 include/linux/shmem_fs.h           |  7 +++++
 kernel/events/uprobes.c            |  2 +-
 mm/filemap_xip.c                   |  2 +-
 mm/memory.c                        | 28 +++++-------------
 mm/oom_kill.c                      |  5 ++--
 mm/rmap.c                          | 17 ++++-------
 mm/shmem.c                         | 35 ++++++++++++++++++++++
 12 files changed, 147 insertions(+), 47 deletions(-)

-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 0/5] mm, shmem: Enhance per-process accounting of shared memory
@ 2014-09-15 14:24 ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Changes since v1:
 - Add VmFile and VmAnon line to /proc/<pid>/status.
 - Split first patch: new accounting code on one side and and adding
 new fields to status on the other.
 - Remove ShmOther and ShmSwapCache from smaps and rename ShmOrphan to
 ShmNotMapped.
 - Drop fourth patch "mm, shmem: Add shmem swap memory accounting".
 - Minor implementation details.

I also tried again to come to a better way to account for shmem swap
pages, but my effort were again unsuccessful. Any suggestion is gladly
welcome.

There are several shortcomings with the accounting of shared memory
(sysV shm, shared anonymous mapping, mapping to a tmpfs file). The
values in /proc/<pid>/status and statm don't allow to distinguish
between shmem memory and a shared mapping to a regular file, even
though theirs implication on memory usage are quite different: at
reclaim, file mapping can be dropped or write back on disk while shmem
needs a place in swap. As for shmem pages that are swapped-out or in
swap cache, they aren't accounted at all.

This series addresses these issues by adding new fields to status and
smaps file in /proc/<pid>/. The accounting of resident shared memory is
made in the same way as it's currently done for resident memory and
general swap (a counter in mm_rss_stat), but this approach proved
impractical for paged-out shared memory (it would requires a rmap walk
each time a page is paged-in).

/proc/<pid>/smaps also lacks proper accounting of shared memory since
shmem subsystem hides all implementation detail to generic mm code.
This series adds the shmem_locate() function that returns the location
of a particular page (resident, in swap or swap cache). Called from
smaps code, it allows to show more detailled accounting of shmem
mappings in smaps.

Patch 1 adds a counter to keep track of resident shmem memory.
Patch 2 adds VmFile, VmAnon and VmShm lines to /proc/<pid>/status.
Patch 3 adds a function to allow generic code to know the physical
location of a shmem page.
Patch 4 adds simple helper function.
Patch 5 adds shmem specific fields to /proc/<pid>/smaps.

Thanks,
Jerome

Jerome Marchand (5):
  mm, shmem: Add shmem resident memory accounting
  mm, procfs: Display VmAnon, VmFile and VmShm in /proc/pid/status
  mm, shmem: Add shmem_locate function
  mm, shmem: Add shmem_vma() helper
  mm, shmem: Show location of non-resident shmem pages in smaps

 Documentation/filesystems/proc.txt | 16 +++++++++-
 arch/s390/mm/pgtable.c             |  5 +---
 fs/proc/task_mmu.c                 | 60 ++++++++++++++++++++++++++++++++++++--
 include/linux/mm.h                 | 10 +++++++
 include/linux/mm_types.h           |  7 +++--
 include/linux/shmem_fs.h           |  7 +++++
 kernel/events/uprobes.c            |  2 +-
 mm/filemap_xip.c                   |  2 +-
 mm/memory.c                        | 28 +++++-------------
 mm/oom_kill.c                      |  5 ++--
 mm/rmap.c                          | 17 ++++-------
 mm/shmem.c                         | 35 ++++++++++++++++++++++
 12 files changed, 147 insertions(+), 47 deletions(-)

-- 
1.9.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 1/5] mm, shmem: Add shmem resident memory accounting
  2014-09-15 14:24 ` Jerome Marchand
@ 2014-09-15 14:24   ` Jerome Marchand
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Currently looking at /proc/<pid>/status or statm, there is no way to
distinguish shmem pages from pages mapped to a regular file (shmem
pages are mapped to /dev/zero), even though their implication in
actual memory use is quite different.
This patch adds MM_SHMEMPAGES counter to mm_rss_stat to account for
shmem pages instead of MM_FILEPAGES.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 arch/s390/mm/pgtable.c   |  5 +----
 fs/proc/task_mmu.c       |  3 ++-
 include/linux/mm.h       | 10 ++++++++++
 include/linux/mm_types.h |  7 ++++---
 kernel/events/uprobes.c  |  2 +-
 mm/filemap_xip.c         |  2 +-
 mm/memory.c              | 28 ++++++++--------------------
 mm/oom_kill.c            |  5 +++--
 mm/rmap.c                | 17 +++++------------
 9 files changed, 35 insertions(+), 44 deletions(-)

diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 296b61a..740ffdf 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -614,10 +614,7 @@ static void gmap_zap_swap_entry(swp_entry_t entry, struct mm_struct *mm)
 	else if (is_migration_entry(entry)) {
 		struct page *page = migration_entry_to_page(entry);
 
-		if (PageAnon(page))
-			dec_mm_counter(mm, MM_ANONPAGES);
-		else
-			dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 	}
 	free_swap_and_cache(entry);
 }
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 7810aba..32657e3 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -77,7 +77,8 @@ unsigned long task_statm(struct mm_struct *mm,
 			 unsigned long *shared, unsigned long *text,
 			 unsigned long *data, unsigned long *resident)
 {
-	*shared = get_mm_counter(mm, MM_FILEPAGES);
+	*shared = get_mm_counter(mm, MM_FILEPAGES) +
+		get_mm_counter(mm, MM_SHMEMPAGES);
 	*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
 								>> PAGE_SHIFT;
 	*data = mm->total_vm - mm->shared_vm;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ebc5f90..a5770b3 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1311,9 +1311,19 @@ static inline void dec_mm_counter(struct mm_struct *mm, int member)
 	atomic_long_dec(&mm->rss_stat.count[member]);
 }
 
+static inline int mm_counter(struct page *page)
+{
+	if (PageAnon(page))
+		return MM_ANONPAGES;
+	if (PageSwapBacked(page))
+		return MM_SHMEMPAGES;
+	return MM_FILEPAGES;
+}
+
 static inline unsigned long get_mm_rss(struct mm_struct *mm)
 {
 	return get_mm_counter(mm, MM_FILEPAGES) +
+		get_mm_counter(mm, MM_SHMEMPAGES) +
 		get_mm_counter(mm, MM_ANONPAGES);
 }
 
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 6e0b286..a89eb2a 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -322,9 +322,10 @@ struct core_state {
 };
 
 enum {
-	MM_FILEPAGES,
-	MM_ANONPAGES,
-	MM_SWAPENTS,
+	MM_FILEPAGES,	/* Resident file mapping pages */
+	MM_ANONPAGES,	/* Resident anonymous pages */
+	MM_SWAPENTS,	/* Anonymous swap entries */
+	MM_SHMEMPAGES,	/* Resident shared memory pages */
 	NR_MM_COUNTERS
 };
 
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1d0af8a..0f660a0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -188,7 +188,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
 	lru_cache_add_active_or_unevictable(kpage, vma);
 
 	if (!PageAnon(page)) {
-		dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 		inc_mm_counter(mm, MM_ANONPAGES);
 	}
 
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index d8d9fe3..85f0e4b 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -194,7 +194,7 @@ retry:
 			flush_cache_page(vma, address, pte_pfn(*pte));
 			pteval = ptep_clear_flush(vma, address, pte);
 			page_remove_rmap(page);
-			dec_mm_counter(mm, MM_FILEPAGES);
+			dec_mm_counter(mm, mm_counter(page));
 			BUG_ON(pte_dirty(pteval));
 			pte_unmap_unlock(pte, ptl);
 			/* must invalidate_page _before_ freeing the page */
diff --git a/mm/memory.c b/mm/memory.c
index 838f929..7c44163 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -829,10 +829,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 			else if (is_migration_entry(entry)) {
 				page = migration_entry_to_page(entry);
 
-				if (PageAnon(page))
-					rss[MM_ANONPAGES]++;
-				else
-					rss[MM_FILEPAGES]++;
+				rss[mm_counter(page)]++;
 
 				if (is_write_migration_entry(entry) &&
 				    is_cow_mapping(vm_flags)) {
@@ -872,10 +869,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 	if (page) {
 		get_page(page);
 		page_dup_rmap(page);
-		if (PageAnon(page))
-			rss[MM_ANONPAGES]++;
-		else
-			rss[MM_FILEPAGES]++;
+		rss[mm_counter(page)]++;
 	}
 
 out_set_pte:
@@ -1128,9 +1122,7 @@ again:
 					pte_file_mksoft_dirty(ptfile);
 				set_pte_at(mm, addr, pte, ptfile);
 			}
-			if (PageAnon(page))
-				rss[MM_ANONPAGES]--;
-			else {
+			if (!PageAnon(page)) {
 				if (pte_dirty(ptent)) {
 					force_flush = 1;
 					set_page_dirty(page);
@@ -1138,8 +1130,8 @@ again:
 				if (pte_young(ptent) &&
 				    likely(!(vma->vm_flags & VM_SEQ_READ)))
 					mark_page_accessed(page);
-				rss[MM_FILEPAGES]--;
 			}
+			rss[mm_counter(page)]--;
 			page_remove_rmap(page);
 			if (unlikely(page_mapcount(page) < 0))
 				print_bad_pte(vma, addr, ptent, page);
@@ -1167,11 +1159,7 @@ again:
 				struct page *page;
 
 				page = migration_entry_to_page(entry);
-
-				if (PageAnon(page))
-					rss[MM_ANONPAGES]--;
-				else
-					rss[MM_FILEPAGES]--;
+				rss[mm_counter(page)]--;
 			}
 			if (unlikely(!free_swap_and_cache(entry)))
 				print_bad_pte(vma, addr, ptent, NULL);
@@ -1494,7 +1482,7 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
 
 	/* Ok, finally just insert the thing.. */
 	get_page(page);
-	inc_mm_counter_fast(mm, MM_FILEPAGES);
+	inc_mm_counter_fast(mm, mm_counter(page));
 	page_add_file_rmap(page);
 	set_pte_at(mm, addr, pte, mk_pte(page, prot));
 
@@ -2216,7 +2204,7 @@ gotten:
 	if (likely(pte_same(*page_table, orig_pte))) {
 		if (old_page) {
 			if (!PageAnon(old_page)) {
-				dec_mm_counter_fast(mm, MM_FILEPAGES);
+				dec_mm_counter_fast(mm, mm_counter(old_page));
 				inc_mm_counter_fast(mm, MM_ANONPAGES);
 			}
 		} else
@@ -2758,7 +2746,7 @@ void do_set_pte(struct vm_area_struct *vma, unsigned long address,
 		inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
 		page_add_new_anon_rmap(page, vma, address);
 	} else {
-		inc_mm_counter_fast(vma->vm_mm, MM_FILEPAGES);
+		inc_mm_counter_fast(vma->vm_mm, mm_counter(page));
 		page_add_file_rmap(page);
 	}
 	set_pte_at(vma->vm_mm, address, pte, entry);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index bbf405a..aab82e5 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -480,10 +480,11 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 
 	/* mm cannot safely be dereferenced after task_unlock(victim) */
 	mm = victim->mm;
-	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
+	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
 		task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
 		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
-		K(get_mm_counter(victim->mm, MM_FILEPAGES)));
+		K(get_mm_counter(victim->mm, MM_FILEPAGES)),
+		K(get_mm_counter(victim->mm, MM_SHMEMPAGES)));
 	task_unlock(victim);
 
 	/*
diff --git a/mm/rmap.c b/mm/rmap.c
index 5fbd0fe..08797b2 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1164,12 +1164,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 	update_hiwater_rss(mm);
 
 	if (PageHWPoison(page) && !(flags & TTU_IGNORE_HWPOISON)) {
-		if (!PageHuge(page)) {
-			if (PageAnon(page))
-				dec_mm_counter(mm, MM_ANONPAGES);
-			else
-				dec_mm_counter(mm, MM_FILEPAGES);
-		}
+		if (!PageHuge(page))
+			dec_mm_counter(mm, mm_counter(page));
 		set_pte_at(mm, address, pte,
 			   swp_entry_to_pte(make_hwpoison_entry(page)));
 	} else if (pte_unused(pteval)) {
@@ -1178,10 +1174,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 		 * interest anymore. Simply discard the pte, vmscan
 		 * will take care of the rest.
 		 */
-		if (PageAnon(page))
-			dec_mm_counter(mm, MM_ANONPAGES);
-		else
-			dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 	} else if (PageAnon(page)) {
 		swp_entry_t entry = { .val = page_private(page) };
 		pte_t swp_pte;
@@ -1225,7 +1218,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 		entry = make_migration_entry(page, pte_write(pteval));
 		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
 	} else
-		dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 
 	page_remove_rmap(page);
 	page_cache_release(page);
@@ -1376,7 +1369,7 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 
 		page_remove_rmap(page);
 		page_cache_release(page);
-		dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 		(*mapcount)--;
 	}
 	pte_unmap_unlock(pte - 1, ptl);
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 1/5] mm, shmem: Add shmem resident memory accounting
@ 2014-09-15 14:24   ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Currently looking at /proc/<pid>/status or statm, there is no way to
distinguish shmem pages from pages mapped to a regular file (shmem
pages are mapped to /dev/zero), even though their implication in
actual memory use is quite different.
This patch adds MM_SHMEMPAGES counter to mm_rss_stat to account for
shmem pages instead of MM_FILEPAGES.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 arch/s390/mm/pgtable.c   |  5 +----
 fs/proc/task_mmu.c       |  3 ++-
 include/linux/mm.h       | 10 ++++++++++
 include/linux/mm_types.h |  7 ++++---
 kernel/events/uprobes.c  |  2 +-
 mm/filemap_xip.c         |  2 +-
 mm/memory.c              | 28 ++++++++--------------------
 mm/oom_kill.c            |  5 +++--
 mm/rmap.c                | 17 +++++------------
 9 files changed, 35 insertions(+), 44 deletions(-)

diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 296b61a..740ffdf 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -614,10 +614,7 @@ static void gmap_zap_swap_entry(swp_entry_t entry, struct mm_struct *mm)
 	else if (is_migration_entry(entry)) {
 		struct page *page = migration_entry_to_page(entry);
 
-		if (PageAnon(page))
-			dec_mm_counter(mm, MM_ANONPAGES);
-		else
-			dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 	}
 	free_swap_and_cache(entry);
 }
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 7810aba..32657e3 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -77,7 +77,8 @@ unsigned long task_statm(struct mm_struct *mm,
 			 unsigned long *shared, unsigned long *text,
 			 unsigned long *data, unsigned long *resident)
 {
-	*shared = get_mm_counter(mm, MM_FILEPAGES);
+	*shared = get_mm_counter(mm, MM_FILEPAGES) +
+		get_mm_counter(mm, MM_SHMEMPAGES);
 	*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
 								>> PAGE_SHIFT;
 	*data = mm->total_vm - mm->shared_vm;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ebc5f90..a5770b3 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1311,9 +1311,19 @@ static inline void dec_mm_counter(struct mm_struct *mm, int member)
 	atomic_long_dec(&mm->rss_stat.count[member]);
 }
 
+static inline int mm_counter(struct page *page)
+{
+	if (PageAnon(page))
+		return MM_ANONPAGES;
+	if (PageSwapBacked(page))
+		return MM_SHMEMPAGES;
+	return MM_FILEPAGES;
+}
+
 static inline unsigned long get_mm_rss(struct mm_struct *mm)
 {
 	return get_mm_counter(mm, MM_FILEPAGES) +
+		get_mm_counter(mm, MM_SHMEMPAGES) +
 		get_mm_counter(mm, MM_ANONPAGES);
 }
 
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 6e0b286..a89eb2a 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -322,9 +322,10 @@ struct core_state {
 };
 
 enum {
-	MM_FILEPAGES,
-	MM_ANONPAGES,
-	MM_SWAPENTS,
+	MM_FILEPAGES,	/* Resident file mapping pages */
+	MM_ANONPAGES,	/* Resident anonymous pages */
+	MM_SWAPENTS,	/* Anonymous swap entries */
+	MM_SHMEMPAGES,	/* Resident shared memory pages */
 	NR_MM_COUNTERS
 };
 
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1d0af8a..0f660a0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -188,7 +188,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
 	lru_cache_add_active_or_unevictable(kpage, vma);
 
 	if (!PageAnon(page)) {
-		dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 		inc_mm_counter(mm, MM_ANONPAGES);
 	}
 
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index d8d9fe3..85f0e4b 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -194,7 +194,7 @@ retry:
 			flush_cache_page(vma, address, pte_pfn(*pte));
 			pteval = ptep_clear_flush(vma, address, pte);
 			page_remove_rmap(page);
-			dec_mm_counter(mm, MM_FILEPAGES);
+			dec_mm_counter(mm, mm_counter(page));
 			BUG_ON(pte_dirty(pteval));
 			pte_unmap_unlock(pte, ptl);
 			/* must invalidate_page _before_ freeing the page */
diff --git a/mm/memory.c b/mm/memory.c
index 838f929..7c44163 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -829,10 +829,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 			else if (is_migration_entry(entry)) {
 				page = migration_entry_to_page(entry);
 
-				if (PageAnon(page))
-					rss[MM_ANONPAGES]++;
-				else
-					rss[MM_FILEPAGES]++;
+				rss[mm_counter(page)]++;
 
 				if (is_write_migration_entry(entry) &&
 				    is_cow_mapping(vm_flags)) {
@@ -872,10 +869,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 	if (page) {
 		get_page(page);
 		page_dup_rmap(page);
-		if (PageAnon(page))
-			rss[MM_ANONPAGES]++;
-		else
-			rss[MM_FILEPAGES]++;
+		rss[mm_counter(page)]++;
 	}
 
 out_set_pte:
@@ -1128,9 +1122,7 @@ again:
 					pte_file_mksoft_dirty(ptfile);
 				set_pte_at(mm, addr, pte, ptfile);
 			}
-			if (PageAnon(page))
-				rss[MM_ANONPAGES]--;
-			else {
+			if (!PageAnon(page)) {
 				if (pte_dirty(ptent)) {
 					force_flush = 1;
 					set_page_dirty(page);
@@ -1138,8 +1130,8 @@ again:
 				if (pte_young(ptent) &&
 				    likely(!(vma->vm_flags & VM_SEQ_READ)))
 					mark_page_accessed(page);
-				rss[MM_FILEPAGES]--;
 			}
+			rss[mm_counter(page)]--;
 			page_remove_rmap(page);
 			if (unlikely(page_mapcount(page) < 0))
 				print_bad_pte(vma, addr, ptent, page);
@@ -1167,11 +1159,7 @@ again:
 				struct page *page;
 
 				page = migration_entry_to_page(entry);
-
-				if (PageAnon(page))
-					rss[MM_ANONPAGES]--;
-				else
-					rss[MM_FILEPAGES]--;
+				rss[mm_counter(page)]--;
 			}
 			if (unlikely(!free_swap_and_cache(entry)))
 				print_bad_pte(vma, addr, ptent, NULL);
@@ -1494,7 +1482,7 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
 
 	/* Ok, finally just insert the thing.. */
 	get_page(page);
-	inc_mm_counter_fast(mm, MM_FILEPAGES);
+	inc_mm_counter_fast(mm, mm_counter(page));
 	page_add_file_rmap(page);
 	set_pte_at(mm, addr, pte, mk_pte(page, prot));
 
@@ -2216,7 +2204,7 @@ gotten:
 	if (likely(pte_same(*page_table, orig_pte))) {
 		if (old_page) {
 			if (!PageAnon(old_page)) {
-				dec_mm_counter_fast(mm, MM_FILEPAGES);
+				dec_mm_counter_fast(mm, mm_counter(old_page));
 				inc_mm_counter_fast(mm, MM_ANONPAGES);
 			}
 		} else
@@ -2758,7 +2746,7 @@ void do_set_pte(struct vm_area_struct *vma, unsigned long address,
 		inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
 		page_add_new_anon_rmap(page, vma, address);
 	} else {
-		inc_mm_counter_fast(vma->vm_mm, MM_FILEPAGES);
+		inc_mm_counter_fast(vma->vm_mm, mm_counter(page));
 		page_add_file_rmap(page);
 	}
 	set_pte_at(vma->vm_mm, address, pte, entry);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index bbf405a..aab82e5 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -480,10 +480,11 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 
 	/* mm cannot safely be dereferenced after task_unlock(victim) */
 	mm = victim->mm;
-	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
+	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
 		task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
 		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
-		K(get_mm_counter(victim->mm, MM_FILEPAGES)));
+		K(get_mm_counter(victim->mm, MM_FILEPAGES)),
+		K(get_mm_counter(victim->mm, MM_SHMEMPAGES)));
 	task_unlock(victim);
 
 	/*
diff --git a/mm/rmap.c b/mm/rmap.c
index 5fbd0fe..08797b2 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1164,12 +1164,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 	update_hiwater_rss(mm);
 
 	if (PageHWPoison(page) && !(flags & TTU_IGNORE_HWPOISON)) {
-		if (!PageHuge(page)) {
-			if (PageAnon(page))
-				dec_mm_counter(mm, MM_ANONPAGES);
-			else
-				dec_mm_counter(mm, MM_FILEPAGES);
-		}
+		if (!PageHuge(page))
+			dec_mm_counter(mm, mm_counter(page));
 		set_pte_at(mm, address, pte,
 			   swp_entry_to_pte(make_hwpoison_entry(page)));
 	} else if (pte_unused(pteval)) {
@@ -1178,10 +1174,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 		 * interest anymore. Simply discard the pte, vmscan
 		 * will take care of the rest.
 		 */
-		if (PageAnon(page))
-			dec_mm_counter(mm, MM_ANONPAGES);
-		else
-			dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 	} else if (PageAnon(page)) {
 		swp_entry_t entry = { .val = page_private(page) };
 		pte_t swp_pte;
@@ -1225,7 +1218,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 		entry = make_migration_entry(page, pte_write(pteval));
 		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
 	} else
-		dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 
 	page_remove_rmap(page);
 	page_cache_release(page);
@@ -1376,7 +1369,7 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 
 		page_remove_rmap(page);
 		page_cache_release(page);
-		dec_mm_counter(mm, MM_FILEPAGES);
+		dec_mm_counter(mm, mm_counter(page));
 		(*mapcount)--;
 	}
 	pte_unmap_unlock(pte - 1, ptl);
-- 
1.9.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 2/5] mm, procfs: Display VmAnon, VmFile and VmShm in /proc/pid/status
  2014-09-15 14:24 ` Jerome Marchand
@ 2014-09-15 14:24   ` Jerome Marchand
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

It's currently inconvenient to retrieve MM_ANONPAGES value from status
and statm files and there is no way to separate MM_FILEPAGES and
MM_SHMEMPAGES. Add VmAnon, VmFile and VmShm lines in /proc/<pid>/status
to solve these issues.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 Documentation/filesystems/proc.txt | 10 +++++++++-
 fs/proc/task_mmu.c                 | 11 ++++++++++-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 154a345..ffd4a7f 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -165,6 +165,9 @@ read the file /proc/PID/status:
   VmLck:         0 kB
   VmHWM:       476 kB
   VmRSS:       476 kB
+  VmAnon:      352 kB
+  VmFile:      124 kB
+  VmShm:         4 kB
   VmData:      156 kB
   VmStk:        88 kB
   VmExe:        68 kB
@@ -221,7 +224,12 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
  VmSize                      total program size
  VmLck                       locked memory size
  VmHWM                       peak resident set size ("high water mark")
- VmRSS                       size of memory portions
+ VmRSS                       size of memory portions. It contains the three
+                             following parts (VmRSS = VmAnon + VmFile + VmShm)
+ VmAnon                      size of resident anonymous memory
+ VmFile                      size of resident file mappings
+ VmShm                       size of resident shmem memory (includes SysV shm,
+                             mapping of tmpfs and shared anonymous mappings)
  VmData                      size of data, stack, and text segments
  VmStk                       size of data, stack, and text segments
  VmExe                       size of text segment
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 32657e3..762257f 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -21,7 +21,7 @@
 
 void task_mem(struct seq_file *m, struct mm_struct *mm)
 {
-	unsigned long data, text, lib, swap;
+	unsigned long data, text, lib, swap, anon, file, shmem;
 	unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
 
 	/*
@@ -38,6 +38,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
 	if (hiwater_rss < mm->hiwater_rss)
 		hiwater_rss = mm->hiwater_rss;
 
+	anon = get_mm_counter(mm, MM_ANONPAGES);
+	file = get_mm_counter(mm, MM_FILEPAGES);
+	shmem = get_mm_counter(mm, MM_SHMEMPAGES);
 	data = mm->total_vm - mm->shared_vm - mm->stack_vm;
 	text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
 	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
@@ -49,6 +52,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
 		"VmPin:\t%8lu kB\n"
 		"VmHWM:\t%8lu kB\n"
 		"VmRSS:\t%8lu kB\n"
+		"VmAnon:\t%8lu kB\n"
+		"VmFile:\t%8lu kB\n"
+		"VmShm:\t%8lu kB\n"
 		"VmData:\t%8lu kB\n"
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
@@ -61,6 +67,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
 		mm->pinned_vm << (PAGE_SHIFT-10),
 		hiwater_rss << (PAGE_SHIFT-10),
 		total_rss << (PAGE_SHIFT-10),
+		anon << (PAGE_SHIFT-10),
+		file << (PAGE_SHIFT-10),
+		shmem << (PAGE_SHIFT-10),
 		data << (PAGE_SHIFT-10),
 		mm->stack_vm << (PAGE_SHIFT-10), text, lib,
 		(PTRS_PER_PTE * sizeof(pte_t) *
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 2/5] mm, procfs: Display VmAnon, VmFile and VmShm in /proc/pid/status
@ 2014-09-15 14:24   ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

It's currently inconvenient to retrieve MM_ANONPAGES value from status
and statm files and there is no way to separate MM_FILEPAGES and
MM_SHMEMPAGES. Add VmAnon, VmFile and VmShm lines in /proc/<pid>/status
to solve these issues.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 Documentation/filesystems/proc.txt | 10 +++++++++-
 fs/proc/task_mmu.c                 | 11 ++++++++++-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 154a345..ffd4a7f 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -165,6 +165,9 @@ read the file /proc/PID/status:
   VmLck:         0 kB
   VmHWM:       476 kB
   VmRSS:       476 kB
+  VmAnon:      352 kB
+  VmFile:      124 kB
+  VmShm:         4 kB
   VmData:      156 kB
   VmStk:        88 kB
   VmExe:        68 kB
@@ -221,7 +224,12 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
  VmSize                      total program size
  VmLck                       locked memory size
  VmHWM                       peak resident set size ("high water mark")
- VmRSS                       size of memory portions
+ VmRSS                       size of memory portions. It contains the three
+                             following parts (VmRSS = VmAnon + VmFile + VmShm)
+ VmAnon                      size of resident anonymous memory
+ VmFile                      size of resident file mappings
+ VmShm                       size of resident shmem memory (includes SysV shm,
+                             mapping of tmpfs and shared anonymous mappings)
  VmData                      size of data, stack, and text segments
  VmStk                       size of data, stack, and text segments
  VmExe                       size of text segment
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 32657e3..762257f 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -21,7 +21,7 @@
 
 void task_mem(struct seq_file *m, struct mm_struct *mm)
 {
-	unsigned long data, text, lib, swap;
+	unsigned long data, text, lib, swap, anon, file, shmem;
 	unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
 
 	/*
@@ -38,6 +38,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
 	if (hiwater_rss < mm->hiwater_rss)
 		hiwater_rss = mm->hiwater_rss;
 
+	anon = get_mm_counter(mm, MM_ANONPAGES);
+	file = get_mm_counter(mm, MM_FILEPAGES);
+	shmem = get_mm_counter(mm, MM_SHMEMPAGES);
 	data = mm->total_vm - mm->shared_vm - mm->stack_vm;
 	text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
 	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
@@ -49,6 +52,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
 		"VmPin:\t%8lu kB\n"
 		"VmHWM:\t%8lu kB\n"
 		"VmRSS:\t%8lu kB\n"
+		"VmAnon:\t%8lu kB\n"
+		"VmFile:\t%8lu kB\n"
+		"VmShm:\t%8lu kB\n"
 		"VmData:\t%8lu kB\n"
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
@@ -61,6 +67,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
 		mm->pinned_vm << (PAGE_SHIFT-10),
 		hiwater_rss << (PAGE_SHIFT-10),
 		total_rss << (PAGE_SHIFT-10),
+		anon << (PAGE_SHIFT-10),
+		file << (PAGE_SHIFT-10),
+		shmem << (PAGE_SHIFT-10),
 		data << (PAGE_SHIFT-10),
 		mm->stack_vm << (PAGE_SHIFT-10), text, lib,
 		(PTRS_PER_PTE * sizeof(pte_t) *
-- 
1.9.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 3/5] mm, shmem: Add shmem_locate function
  2014-09-15 14:24 ` Jerome Marchand
@ 2014-09-15 14:24   ` Jerome Marchand
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

The shmem subsytem is kind of a black box: the generic mm code can't
always know where a specific page physically is. This patch adds the
shmem_locate() function to find out the physical location of shmem
pages (resident, in swap or swapcache). If the optional argument count
isn't NULL and the page is resident, it also returns the mapcount value
of this page.
This is intended to allow finer accounting of shmem/tmpfs pages.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 include/linux/shmem_fs.h |  6 ++++++
 mm/shmem.c               | 29 +++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 50777b5..99992cf 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -42,6 +42,11 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 	return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+#define SHMEM_NOTPRESENT	1 /* page is not present in memory */
+#define SHMEM_RESIDENT		2 /* page is resident in RAM */
+#define SHMEM_SWAPCACHE		3 /* page is in swap cache */
+#define SHMEM_SWAP		4 /* page is paged out */
+
 /*
  * Functions in mm/shmem.c called directly from elsewhere:
  */
@@ -59,6 +64,7 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					pgoff_t index, gfp_t gfp_mask);
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
 extern int shmem_unuse(swp_entry_t entry, struct page *page);
+extern int shmem_locate(struct vm_area_struct *vma, pgoff_t pgoff, int *count);
 
 static inline struct page *shmem_read_mapping_page(
 				struct address_space *mapping, pgoff_t index)
diff --git a/mm/shmem.c b/mm/shmem.c
index d547345..134a422 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1350,6 +1350,35 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	return ret;
 }
 
+int shmem_locate(struct vm_area_struct *vma, pgoff_t pgoff, int *count)
+{
+	struct address_space *mapping = file_inode(vma->vm_file)->i_mapping;
+	struct page *page;
+	swp_entry_t swap;
+	int ret;
+
+	page = find_get_entry(mapping, pgoff);
+	if (!page) /* Not yet initialised? */
+		return SHMEM_NOTPRESENT;
+
+	if (!radix_tree_exceptional_entry(page)) {
+		ret = SHMEM_RESIDENT;
+		if (count)
+			*count = page_mapcount(page);
+		goto out;
+	}
+
+	swap = radix_to_swp_entry(page);
+	page = find_get_page(swap_address_space(swap), swap.val);
+	if (!page)
+		return SHMEM_SWAP;
+	ret = SHMEM_SWAPCACHE;
+
+out:
+	page_cache_release(page);
+	return ret;
+}
+
 #ifdef CONFIG_NUMA
 static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *mpol)
 {
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 3/5] mm, shmem: Add shmem_locate function
@ 2014-09-15 14:24   ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

The shmem subsytem is kind of a black box: the generic mm code can't
always know where a specific page physically is. This patch adds the
shmem_locate() function to find out the physical location of shmem
pages (resident, in swap or swapcache). If the optional argument count
isn't NULL and the page is resident, it also returns the mapcount value
of this page.
This is intended to allow finer accounting of shmem/tmpfs pages.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 include/linux/shmem_fs.h |  6 ++++++
 mm/shmem.c               | 29 +++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 50777b5..99992cf 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -42,6 +42,11 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 	return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+#define SHMEM_NOTPRESENT	1 /* page is not present in memory */
+#define SHMEM_RESIDENT		2 /* page is resident in RAM */
+#define SHMEM_SWAPCACHE		3 /* page is in swap cache */
+#define SHMEM_SWAP		4 /* page is paged out */
+
 /*
  * Functions in mm/shmem.c called directly from elsewhere:
  */
@@ -59,6 +64,7 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					pgoff_t index, gfp_t gfp_mask);
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
 extern int shmem_unuse(swp_entry_t entry, struct page *page);
+extern int shmem_locate(struct vm_area_struct *vma, pgoff_t pgoff, int *count);
 
 static inline struct page *shmem_read_mapping_page(
 				struct address_space *mapping, pgoff_t index)
diff --git a/mm/shmem.c b/mm/shmem.c
index d547345..134a422 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1350,6 +1350,35 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	return ret;
 }
 
+int shmem_locate(struct vm_area_struct *vma, pgoff_t pgoff, int *count)
+{
+	struct address_space *mapping = file_inode(vma->vm_file)->i_mapping;
+	struct page *page;
+	swp_entry_t swap;
+	int ret;
+
+	page = find_get_entry(mapping, pgoff);
+	if (!page) /* Not yet initialised? */
+		return SHMEM_NOTPRESENT;
+
+	if (!radix_tree_exceptional_entry(page)) {
+		ret = SHMEM_RESIDENT;
+		if (count)
+			*count = page_mapcount(page);
+		goto out;
+	}
+
+	swap = radix_to_swp_entry(page);
+	page = find_get_page(swap_address_space(swap), swap.val);
+	if (!page)
+		return SHMEM_SWAP;
+	ret = SHMEM_SWAPCACHE;
+
+out:
+	page_cache_release(page);
+	return ret;
+}
+
 #ifdef CONFIG_NUMA
 static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *mpol)
 {
-- 
1.9.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 4/5] mm, shmem: Add shmem_vma() helper
  2014-09-15 14:24 ` Jerome Marchand
@ 2014-09-15 14:24   ` Jerome Marchand
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Add a simple helper to check if a vm area belongs to shmem.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 include/linux/shmem_fs.h | 1 +
 mm/shmem.c               | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 99992cf..b1fd7c1 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -59,6 +59,7 @@ extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
 extern bool shmem_mapping(struct address_space *mapping);
+extern bool shmem_vma(struct vm_area_struct *vma);
 extern void shmem_unlock_mapping(struct address_space *mapping);
 extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					pgoff_t index, gfp_t gfp_mask);
diff --git a/mm/shmem.c b/mm/shmem.c
index 134a422..e2d7be6 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1493,6 +1493,12 @@ bool shmem_mapping(struct address_space *mapping)
 	return mapping->backing_dev_info == &shmem_backing_dev_info;
 }
 
+bool shmem_vma(struct vm_area_struct *vma)
+{
+	return vma->vm_file &&
+		shmem_mapping(file_inode(vma->vm_file)->i_mapping);
+}
+
 #ifdef CONFIG_TMPFS
 static const struct inode_operations shmem_symlink_inode_operations;
 static const struct inode_operations shmem_short_symlink_operations;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 4/5] mm, shmem: Add shmem_vma() helper
@ 2014-09-15 14:24   ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Add a simple helper to check if a vm area belongs to shmem.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 include/linux/shmem_fs.h | 1 +
 mm/shmem.c               | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 99992cf..b1fd7c1 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -59,6 +59,7 @@ extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
 extern bool shmem_mapping(struct address_space *mapping);
+extern bool shmem_vma(struct vm_area_struct *vma);
 extern void shmem_unlock_mapping(struct address_space *mapping);
 extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					pgoff_t index, gfp_t gfp_mask);
diff --git a/mm/shmem.c b/mm/shmem.c
index 134a422..e2d7be6 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1493,6 +1493,12 @@ bool shmem_mapping(struct address_space *mapping)
 	return mapping->backing_dev_info == &shmem_backing_dev_info;
 }
 
+bool shmem_vma(struct vm_area_struct *vma)
+{
+	return vma->vm_file &&
+		shmem_mapping(file_inode(vma->vm_file)->i_mapping);
+}
+
 #ifdef CONFIG_TMPFS
 static const struct inode_operations shmem_symlink_inode_operations;
 static const struct inode_operations shmem_short_symlink_operations;
-- 
1.9.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
  2014-09-15 14:24 ` Jerome Marchand
@ 2014-09-15 14:24   ` Jerome Marchand
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Adds ShmSwap and ShmNotMapped lines to /proc/<pid>/smaps for shmem
mappings.

ShmSwap: amount of memory that is paged out on disk.
ShmNotMapped: amount of memory that is currently resident in memory but
not mapped into any process. This can happens when a process unmaps a
shared mapping or exits and no other process had acccessed the page.
Despite being resident, this memory is not currently accounted to any
process and since it belongs to the mapping of another process, it can
not be discarded.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 Documentation/filesystems/proc.txt |  6 +++++
 fs/proc/task_mmu.c                 | 46 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index ffd4a7f..21eb614 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -426,6 +426,8 @@ Swap:                  0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 Locked:              374 kB
+ShmSwap:              36 kB
+ShmNotMapped:          0 kB
 VmFlags: rd ex mr mw me de
 
 the first of these lines shows the same information as is displayed for the
@@ -441,6 +443,10 @@ a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE
 and a page is modified, the file page is replaced by a private anonymous copy.
 "Swap" shows how much would-be-anonymous memory is also used, but out on
 swap.
+The ShmXXX lines only appears for shmem mapping. They show the amount of memory
+from the mapping that is currently:
+ - resident in RAM but not mapped into any process (ShmNotMapped)
+ - paged out on swap (ShmSwap).
 
 "VmFlags" field deserves a separate description. This member represents the kernel
 flags associated with the particular virtual memory area in two letter encoded
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 762257f..b697bf5 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -13,6 +13,7 @@
 #include <linux/swap.h>
 #include <linux/swapops.h>
 #include <linux/mmu_notifier.h>
+#include <linux/shmem_fs.h>
 
 #include <asm/elf.h>
 #include <asm/uaccess.h>
@@ -455,9 +456,26 @@ struct mem_size_stats {
 	unsigned long anonymous_thp;
 	unsigned long swap;
 	unsigned long nonlinear;
+	unsigned long shmem_swap;
+	unsigned long shmem_notmapped;
 	u64 pss;
 };
 
+void update_shmem_stats(struct mem_size_stats *mss, struct vm_area_struct *vma,
+			pgoff_t pgoff, unsigned long size)
+{
+	int count = 0;
+
+	switch (shmem_locate(vma, pgoff, &count)) {
+	case SHMEM_RESIDENT:
+		if (!count)
+			mss->shmem_notmapped += size;
+		break;
+	case SHMEM_SWAP:
+		mss->shmem_swap += size;
+		break;
+	}
+}
 
 static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 		unsigned long ptent_size, struct mm_walk *walk)
@@ -480,7 +498,8 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 	} else if (pte_file(ptent)) {
 		if (pte_to_pgoff(ptent) != pgoff)
 			mss->nonlinear += ptent_size;
-	}
+	} else if (pte_none(ptent) && shmem_vma(vma))
+		update_shmem_stats(mss, vma, pgoff, ptent_size);
 
 	if (!page)
 		return;
@@ -541,6 +560,21 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 	return 0;
 }
 
+static int smaps_pte_hole(unsigned long addr, unsigned long end,
+			  struct mm_walk *walk)
+{
+	struct mem_size_stats *mss = walk->private;
+	struct vm_area_struct *vma = mss->vma;
+	pgoff_t pgoff;
+
+	for (; addr != end; addr += PAGE_SIZE) {
+		pgoff = linear_page_index(vma, addr);
+		update_shmem_stats(mss, vma, pgoff, PAGE_SIZE);
+	}
+
+	return 0;
+}
+
 static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
 {
 	/*
@@ -605,6 +639,10 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 		.private = &mss,
 	};
 
+	/* Only walk the holes when it'a a shmem mapping */
+	if (shmem_vma(vma))
+		smaps_walk.pte_hole = smaps_pte_hole;
+
 	memset(&mss, 0, sizeof mss);
 	mss.vma = vma;
 	/* mmap_sem is held in m_start */
@@ -647,6 +685,12 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 	if (vma->vm_flags & VM_NONLINEAR)
 		seq_printf(m, "Nonlinear:      %8lu kB\n",
 				mss.nonlinear >> 10);
+	if (shmem_vma(vma))
+		seq_printf(m,
+			   "ShmSwap:        %8lu kB\n"
+			   "ShmNotMapped:   %8lu kB\n",
+			   mss.shmem_swap >> 10,
+			   mss.shmem_notmapped >> 10);
 
 	show_smap_vma_flags(m, vma);
 	m_cache_vma(m, vma);
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
@ 2014-09-15 14:24   ` Jerome Marchand
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 14:24 UTC (permalink / raw)
  To: linux-mm
  Cc: Randy Dunlap, Martin Schwidefsky, Heiko Carstens, linux390,
	Hugh Dickins, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
	Arnaldo Carvalho de Melo, linux-doc, linux-kernel, linux-s390,
	Oleg Nesterov

Adds ShmSwap and ShmNotMapped lines to /proc/<pid>/smaps for shmem
mappings.

ShmSwap: amount of memory that is paged out on disk.
ShmNotMapped: amount of memory that is currently resident in memory but
not mapped into any process. This can happens when a process unmaps a
shared mapping or exits and no other process had acccessed the page.
Despite being resident, this memory is not currently accounted to any
process and since it belongs to the mapping of another process, it can
not be discarded.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
 Documentation/filesystems/proc.txt |  6 +++++
 fs/proc/task_mmu.c                 | 46 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index ffd4a7f..21eb614 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -426,6 +426,8 @@ Swap:                  0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 Locked:              374 kB
+ShmSwap:              36 kB
+ShmNotMapped:          0 kB
 VmFlags: rd ex mr mw me de
 
 the first of these lines shows the same information as is displayed for the
@@ -441,6 +443,10 @@ a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE
 and a page is modified, the file page is replaced by a private anonymous copy.
 "Swap" shows how much would-be-anonymous memory is also used, but out on
 swap.
+The ShmXXX lines only appears for shmem mapping. They show the amount of memory
+from the mapping that is currently:
+ - resident in RAM but not mapped into any process (ShmNotMapped)
+ - paged out on swap (ShmSwap).
 
 "VmFlags" field deserves a separate description. This member represents the kernel
 flags associated with the particular virtual memory area in two letter encoded
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 762257f..b697bf5 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -13,6 +13,7 @@
 #include <linux/swap.h>
 #include <linux/swapops.h>
 #include <linux/mmu_notifier.h>
+#include <linux/shmem_fs.h>
 
 #include <asm/elf.h>
 #include <asm/uaccess.h>
@@ -455,9 +456,26 @@ struct mem_size_stats {
 	unsigned long anonymous_thp;
 	unsigned long swap;
 	unsigned long nonlinear;
+	unsigned long shmem_swap;
+	unsigned long shmem_notmapped;
 	u64 pss;
 };
 
+void update_shmem_stats(struct mem_size_stats *mss, struct vm_area_struct *vma,
+			pgoff_t pgoff, unsigned long size)
+{
+	int count = 0;
+
+	switch (shmem_locate(vma, pgoff, &count)) {
+	case SHMEM_RESIDENT:
+		if (!count)
+			mss->shmem_notmapped += size;
+		break;
+	case SHMEM_SWAP:
+		mss->shmem_swap += size;
+		break;
+	}
+}
 
 static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 		unsigned long ptent_size, struct mm_walk *walk)
@@ -480,7 +498,8 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 	} else if (pte_file(ptent)) {
 		if (pte_to_pgoff(ptent) != pgoff)
 			mss->nonlinear += ptent_size;
-	}
+	} else if (pte_none(ptent) && shmem_vma(vma))
+		update_shmem_stats(mss, vma, pgoff, ptent_size);
 
 	if (!page)
 		return;
@@ -541,6 +560,21 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 	return 0;
 }
 
+static int smaps_pte_hole(unsigned long addr, unsigned long end,
+			  struct mm_walk *walk)
+{
+	struct mem_size_stats *mss = walk->private;
+	struct vm_area_struct *vma = mss->vma;
+	pgoff_t pgoff;
+
+	for (; addr != end; addr += PAGE_SIZE) {
+		pgoff = linear_page_index(vma, addr);
+		update_shmem_stats(mss, vma, pgoff, PAGE_SIZE);
+	}
+
+	return 0;
+}
+
 static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
 {
 	/*
@@ -605,6 +639,10 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 		.private = &mss,
 	};
 
+	/* Only walk the holes when it'a a shmem mapping */
+	if (shmem_vma(vma))
+		smaps_walk.pte_hole = smaps_pte_hole;
+
 	memset(&mss, 0, sizeof mss);
 	mss.vma = vma;
 	/* mmap_sem is held in m_start */
@@ -647,6 +685,12 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 	if (vma->vm_flags & VM_NONLINEAR)
 		seq_printf(m, "Nonlinear:      %8lu kB\n",
 				mss.nonlinear >> 10);
+	if (shmem_vma(vma))
+		seq_printf(m,
+			   "ShmSwap:        %8lu kB\n"
+			   "ShmNotMapped:   %8lu kB\n",
+			   mss.shmem_swap >> 10,
+			   mss.shmem_notmapped >> 10);
 
 	show_smap_vma_flags(m, vma);
 	m_cache_vma(m, vma);
-- 
1.9.3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
  2014-09-15 14:24   ` Jerome Marchand
@ 2014-09-15 16:21     ` Oleg Nesterov
  -1 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2014-09-15 16:21 UTC (permalink / raw)
  To: Jerome Marchand
  Cc: linux-mm, Randy Dunlap, Martin Schwidefsky, Heiko Carstens,
	linux390, Hugh Dickins, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Arnaldo Carvalho de Melo, linux-doc, linux-kernel,
	linux-s390

Hi Jerome,

Not sure I understand this patch correctly, will try to read it later.
But a couple of nits/questions anyway,

On 09/15, Jerome Marchand wrote:
>
> +The ShmXXX lines only appears for shmem mapping. They show the amount of memory
> +from the mapping that is currently:
> + - resident in RAM but not mapped into any process (ShmNotMapped)

But how can we know that it is not mapped by another process?

And in fact "not mapped" looks confusing (at least to me). IIUC it is actually
mapped even by this process, just it never tried to fault these (resident or
swapped) pages in. Right?

> +void update_shmem_stats(struct mem_size_stats *mss, struct vm_area_struct *vma,
> +			pgoff_t pgoff, unsigned long size)

static?

> +{
> +	int count = 0;
> +
> +	switch (shmem_locate(vma, pgoff, &count)) {
> +	case SHMEM_RESIDENT:
> +		if (!count)
> +			mss->shmem_notmapped += size;
> +		break;
> +	case SHMEM_SWAP:
> +		mss->shmem_swap += size;
> +		break;
> +	}
> +}

It seems that shmem_locate() and shmem_vma() are only defined if CONFIG_SHMEM,
probably this series needs more ifdef's.

And I am not sure why we ignore SHMEM_SWAPCACHE...

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
@ 2014-09-15 16:21     ` Oleg Nesterov
  0 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2014-09-15 16:21 UTC (permalink / raw)
  To: Jerome Marchand
  Cc: linux-mm, Randy Dunlap, Martin Schwidefsky, Heiko Carstens,
	linux390, Hugh Dickins, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Arnaldo Carvalho de Melo, linux-doc, linux-kernel,
	linux-s390

Hi Jerome,

Not sure I understand this patch correctly, will try to read it later.
But a couple of nits/questions anyway,

On 09/15, Jerome Marchand wrote:
>
> +The ShmXXX lines only appears for shmem mapping. They show the amount of memory
> +from the mapping that is currently:
> + - resident in RAM but not mapped into any process (ShmNotMapped)

But how can we know that it is not mapped by another process?

And in fact "not mapped" looks confusing (at least to me). IIUC it is actually
mapped even by this process, just it never tried to fault these (resident or
swapped) pages in. Right?

> +void update_shmem_stats(struct mem_size_stats *mss, struct vm_area_struct *vma,
> +			pgoff_t pgoff, unsigned long size)

static?

> +{
> +	int count = 0;
> +
> +	switch (shmem_locate(vma, pgoff, &count)) {
> +	case SHMEM_RESIDENT:
> +		if (!count)
> +			mss->shmem_notmapped += size;
> +		break;
> +	case SHMEM_SWAP:
> +		mss->shmem_swap += size;
> +		break;
> +	}
> +}

It seems that shmem_locate() and shmem_vma() are only defined if CONFIG_SHMEM,
probably this series needs more ifdef's.

And I am not sure why we ignore SHMEM_SWAPCACHE...

Oleg.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
  2014-09-15 16:21     ` Oleg Nesterov
  (?)
@ 2014-09-15 16:47     ` Jerome Marchand
  2014-09-15 17:29         ` Oleg Nesterov
  -1 siblings, 1 reply; 17+ messages in thread
From: Jerome Marchand @ 2014-09-15 16:47 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: linux-mm, Randy Dunlap, Martin Schwidefsky, Heiko Carstens,
	linux390, Hugh Dickins, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Arnaldo Carvalho de Melo, linux-doc, linux-kernel,
	linux-s390

[-- Attachment #1: Type: text/plain, Size: 1782 bytes --]

On 09/15/2014 06:21 PM, Oleg Nesterov wrote:
> Hi Jerome,
> 
> Not sure I understand this patch correctly, will try to read it later.
> But a couple of nits/questions anyway,
> 
> On 09/15, Jerome Marchand wrote:
>>
>> +The ShmXXX lines only appears for shmem mapping. They show the amount of memory
>> +from the mapping that is currently:
>> + - resident in RAM but not mapped into any process (ShmNotMapped)
> 
> But how can we know that it is not mapped by another process?

Its mapcount is zero.

> 
> And in fact "not mapped" looks confusing (at least to me).

"Not mapped" as "not present in a page table". It does belong to a
userspace mapping though. I wonder if there is a less ambiguous terminology.

> IIUC it is actually
> mapped even by this process, just it never tried to fault these (resident or
> swapped) pages in. Right?

No these pages are in the page cache. This can happen when the only
process which have accessed these exits or munmap() the mapping.

> 
>> +void update_shmem_stats(struct mem_size_stats *mss, struct vm_area_struct *vma,
>> +			pgoff_t pgoff, unsigned long size)
> 
> static?
> 
>> +{
>> +	int count = 0;
>> +
>> +	switch (shmem_locate(vma, pgoff, &count)) {
>> +	case SHMEM_RESIDENT:
>> +		if (!count)
>> +			mss->shmem_notmapped += size;
>> +		break;
>> +	case SHMEM_SWAP:
>> +		mss->shmem_swap += size;
>> +		break;
>> +	}
>> +}
> 
> It seems that shmem_locate() and shmem_vma() are only defined if CONFIG_SHMEM,
> probably this series needs more ifdef's.

Now I wonder. Did I try to compile this with CONFIG_SHMEM unset?

> 
> And I am not sure why we ignore SHMEM_SWAPCACHE...

Hugh didn't like it as it is a small and transient value.

Thanks,
Jerome

> 
> Oleg.
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
  2014-09-15 16:47     ` Jerome Marchand
@ 2014-09-15 17:29         ` Oleg Nesterov
  0 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2014-09-15 17:29 UTC (permalink / raw)
  To: Jerome Marchand
  Cc: linux-mm, Randy Dunlap, Martin Schwidefsky, Heiko Carstens,
	linux390, Hugh Dickins, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Arnaldo Carvalho de Melo, linux-doc, linux-kernel,
	linux-s390

On 09/15, Jerome Marchand wrote:
>
> On 09/15/2014 06:21 PM, Oleg Nesterov wrote:
> > Hi Jerome,
> >
> > Not sure I understand this patch correctly, will try to read it later.
> > But a couple of nits/questions anyway,
> >
> > On 09/15, Jerome Marchand wrote:
> >>
> >> +The ShmXXX lines only appears for shmem mapping. They show the amount of memory
> >> +from the mapping that is currently:
> >> + - resident in RAM but not mapped into any process (ShmNotMapped)
> >
> > But how can we know that it is not mapped by another process?
>
> Its mapcount is zero.

Ah, yes, I missed the "!count" check. Thanks!

> > And in fact "not mapped" looks confusing (at least to me).
>
> "Not mapped" as "not present in a page table". It does belong to a
> userspace mapping though. I wonder if there is a less ambiguous terminology.

To me "not present in page tables" looks more understandable, but I won't
insist.

> > IIUC it is actually
> > mapped even by this process, just it never tried to fault these (resident or
> > swapped) pages in. Right?
>
> No these pages are in the page cache. This can happen when the only
> process which have accessed these exits or munmap() the mapping.

Yes, yes, I meant that this process didn't touch these pages and thus
pte_none() == T.

> > And I am not sure why we ignore SHMEM_SWAPCACHE...
>
> Hugh didn't like it as it is a small and transient value.

OK, but perhaps update_shmem_stats() should treat it as SHMEM_SWAP.
Nevermind, I leave this to you and Hugh.

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps
@ 2014-09-15 17:29         ` Oleg Nesterov
  0 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2014-09-15 17:29 UTC (permalink / raw)
  To: Jerome Marchand
  Cc: linux-mm, Randy Dunlap, Martin Schwidefsky, Heiko Carstens,
	linux390, Hugh Dickins, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Arnaldo Carvalho de Melo, linux-doc, linux-kernel,
	linux-s390

On 09/15, Jerome Marchand wrote:
>
> On 09/15/2014 06:21 PM, Oleg Nesterov wrote:
> > Hi Jerome,
> >
> > Not sure I understand this patch correctly, will try to read it later.
> > But a couple of nits/questions anyway,
> >
> > On 09/15, Jerome Marchand wrote:
> >>
> >> +The ShmXXX lines only appears for shmem mapping. They show the amount of memory
> >> +from the mapping that is currently:
> >> + - resident in RAM but not mapped into any process (ShmNotMapped)
> >
> > But how can we know that it is not mapped by another process?
>
> Its mapcount is zero.

Ah, yes, I missed the "!count" check. Thanks!

> > And in fact "not mapped" looks confusing (at least to me).
>
> "Not mapped" as "not present in a page table". It does belong to a
> userspace mapping though. I wonder if there is a less ambiguous terminology.

To me "not present in page tables" looks more understandable, but I won't
insist.

> > IIUC it is actually
> > mapped even by this process, just it never tried to fault these (resident or
> > swapped) pages in. Right?
>
> No these pages are in the page cache. This can happen when the only
> process which have accessed these exits or munmap() the mapping.

Yes, yes, I meant that this process didn't touch these pages and thus
pte_none() == T.

> > And I am not sure why we ignore SHMEM_SWAPCACHE...
>
> Hugh didn't like it as it is a small and transient value.

OK, but perhaps update_shmem_stats() should treat it as SHMEM_SWAP.
Nevermind, I leave this to you and Hugh.

Oleg.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2014-09-15 17:32 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-15 14:24 [RFC PATCH v2 0/5] mm, shmem: Enhance per-process accounting of shared memory Jerome Marchand
2014-09-15 14:24 ` Jerome Marchand
2014-09-15 14:24 ` [RFC PATCH v2 1/5] mm, shmem: Add shmem resident memory accounting Jerome Marchand
2014-09-15 14:24   ` Jerome Marchand
2014-09-15 14:24 ` [RFC PATCH v2 2/5] mm, procfs: Display VmAnon, VmFile and VmShm in /proc/pid/status Jerome Marchand
2014-09-15 14:24   ` Jerome Marchand
2014-09-15 14:24 ` [RFC PATCH v2 3/5] mm, shmem: Add shmem_locate function Jerome Marchand
2014-09-15 14:24   ` Jerome Marchand
2014-09-15 14:24 ` [RFC PATCH v2 4/5] mm, shmem: Add shmem_vma() helper Jerome Marchand
2014-09-15 14:24   ` Jerome Marchand
2014-09-15 14:24 ` [RFC PATCH v2 5/5] mm, shmem: Show location of non-resident shmem pages in smaps Jerome Marchand
2014-09-15 14:24   ` Jerome Marchand
2014-09-15 16:21   ` Oleg Nesterov
2014-09-15 16:21     ` Oleg Nesterov
2014-09-15 16:47     ` Jerome Marchand
2014-09-15 17:29       ` Oleg Nesterov
2014-09-15 17:29         ` Oleg Nesterov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.