Kernel commit eca56ff906bd ("mm, shmem: add internal shmem resident
memory accounting"), which adds internal shmem resident memory
accounting, and tallies into the mm_rss_stat counter.
As a result, the "ps/vm" commands fail to show correct memory usage when
a process uses an anonymous shared memory region.
Without the patch:
crash> ps 2150
PID PPID CPU TASK ST %MEM VSZ RSS COMM
2150 2105 14 ffff8fba86d74d40 IN 0.0 10488392 444 mmap_test
^^^
Currently, the "ps/vm" commands missed the shmem pages count, let's
count the shmem pages together with regular files and anonymous pages.
With the patch:
crash> ps 2150
PID PPID CPU TASK ST %MEM VSZ RSS COMM
2150 2105 14 ffff8fba86d74d40 IN 20.8 10488392 3659008 mmap_test
Reported-by: Buland Kumar Singh <bsingh(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 +
memory.c | 59 ++++++++++++++++++++++++++++++++++++++++++--------------
task.c | 1 +
3 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/defs.h b/defs.h
index 5ee60f1eb3a5..f784d40c0b17 100644
--- a/defs.h
+++ b/defs.h
@@ -887,6 +887,7 @@ struct task_table { /* kernel/local task table
data */
int callbacks;
struct task_context **context_by_task; /* task_context sorted by task addr */
ulong pid_xarray;
+ long shmempages;
};
#define TASK_INIT_DONE (0x1)
diff --git a/memory.c b/memory.c
index acbee6389472..df85b69963b6 100644
--- a/memory.c
+++ b/memory.c
@@ -4466,13 +4466,13 @@ in_user_stack(ulong task, ulong vaddr)
}
/*
- * Set the const value of filepages and anonpages
- * according to MM_FILEPAGES and MM_ANONPAGES.
+ * Set the const value of filepages, anonpages and shmempages
+ * according to MM_FILEPAGES, MM_ANONPAGES and MM_SHMEMPAGES.
*/
static void
rss_page_types_init(void)
{
- long anonpages, filepages;
+ long anonpages, filepages, shmempages;
if (VALID_MEMBER(mm_struct_rss))
return;
@@ -4487,6 +4487,15 @@ rss_page_types_init(void)
}
tt->filepages = filepages;
tt->anonpages = anonpages;
+
+ /*
+ * The default value(MM_SHMEMPAGES) is 3, which is introduced
+ * in linux v4.5-rc1 and later. See commit eca56ff906bd.
+ */
+ if (!enumerator_value("MM_SHMEMPAGES", &shmempages))
+ tt->shmempages = -1;
+ else
+ tt->shmempages = shmempages;
}
}
@@ -4812,10 +4821,11 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
* Latest kernels have mm_struct.mm_rss_stat[].
*/
if (VALID_MEMBER(mm_struct_rss_stat) && VALID_MEMBER(mm_rss_stat_count)) {
- long anonpages, filepages, count;
+ long anonpages, filepages, shmempages, count;
anonpages = tt->anonpages;
filepages = tt->filepages;
+ shmempages = tt->shmempages;
count = LONG(tt->mm_struct +
OFFSET(mm_struct_rss_stat) +
OFFSET(mm_rss_stat_count) +
@@ -4836,6 +4846,15 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (count > 0)
rss += count;
+ if (shmempages > 0) {
+ count = LONG(tt->mm_struct +
+ OFFSET(mm_struct_rss_stat) +
+ OFFSET(mm_rss_stat_count) +
+ (shmempages * sizeof(long)));
+ if (count > 0)
+ rss += count;
+ }
+
} else if (VALID_MEMBER(mm_struct_rss_stat)) {
/* 6.2: struct percpu_counter rss_stat[NR_MM_COUNTERS] */
ulong fbc;
@@ -4847,6 +4866,10 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) +
(tt->anonpages * SIZE(percpu_counter));
rss += percpu_counter_sum_positive(fbc);
+
+ fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) +
+ (tt->shmempages * SIZE(percpu_counter));
+ rss += percpu_counter_sum_positive(fbc);
}
/* Check whether SPLIT_RSS_COUNTING is enabled */
@@ -4880,12 +4903,11 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (ACTIVE() || last->rss_cache == UNINITIALIZED) {
while (first <= last)
{
+ ulong addr = first->task + OFFSET(task_struct_rss_stat) +
+ OFFSET(task_rss_stat_count);
+
/* count 0 -> filepages */
- if (!readmem(first->task +
- OFFSET(task_struct_rss_stat) +
- OFFSET(task_rss_stat_count), KVADDR,
- &sync_rss,
- sizeof(int),
+ if (!readmem(addr, KVADDR, &sync_rss, sizeof(int),
"task_struct rss_stat MM_FILEPAGES",
RETURN_ON_ERROR))
continue;
@@ -4894,12 +4916,7 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
rss_cache += sync_rss;
/* count 1 -> anonpages */
- if (!readmem(first->task +
- OFFSET(task_struct_rss_stat) +
- OFFSET(task_rss_stat_count) +
- sizeof(int),
- KVADDR, &sync_rss,
- sizeof(int),
+ if (!readmem(addr + sizeof(int), KVADDR, &sync_rss, sizeof(int),
"task_struct rss_stat MM_ANONPAGES",
RETURN_ON_ERROR))
continue;
@@ -4907,6 +4924,18 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (sync_rss > 0)
rss_cache += sync_rss;
+ /* count 3 -> shmempages */
+ if (tt->shmempages > 0) {
+ if (!readmem(addr + tt->shmempages * sizeof(int), KVADDR,
+ &sync_rss, sizeof(int),
+ "task_struct rss_stat MM_SHMEMPAGES",
+ RETURN_ON_ERROR))
+ continue;
+
+ if (sync_rss > 0)
+ rss_cache += sync_rss;
+ }
+
if (first == last)
break;
first++;
diff --git a/task.c b/task.c
index c9206f50c679..4018a543b715 100644
--- a/task.c
+++ b/task.c
@@ -7873,6 +7873,7 @@ dump_task_table(int verbose)
fprintf(fp, " init_pid_ns: %lx\n", tt->init_pid_ns);
fprintf(fp, " filepages: %ld\n", tt->filepages);
fprintf(fp, " anonpages: %ld\n", tt->anonpages);
+ fprintf(fp, " shmempages: %ld\n", tt->shmempages);
fprintf(fp, " stack_end_magic: %lx\n", tt->stack_end_magic);
fprintf(fp, " pf_kthread: %lx ", tt->pf_kthread);
switch (tt->pf_kthread)
--
2.37.1