| From: Swarup Laxman Kotiaklapudi <swarupkotikalapudi@gmail.com> |
| Subject: proc: test /proc/${pid}/statm |
| Date: Mon, 9 Oct 2023 14:07:14 +0300 |
| |
| |
| My original comment lied, output can be "0 A A B 0 0 0\n" |
| (see comment in the code). |
| |
| I don't quite understand why |
| |
| get_mm_counter(mm, MM_FILEPAGES) + get_mm_counter(mm, MM_SHMEMPAGES) |
| |
| can stay positive but get_mm_counter(mm, MM_ANONPAGES) is always 0 after |
| everything is unmapped but that's just me. |
| |
| [adobriyan@gmail.com: more or less rewritten] |
| Link: https://lkml.kernel.org/r/0721ca69-7bb4-40aa-8d01-0c5f91e5f363@p183 |
| Signed-off-by: Swarup Laxman Kotiaklapudi <swarupkotikalapudi@gmail.com> |
| Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| tools/testing/selftests/proc/proc-empty-vm.c | 97 ++++++++++++++++- |
| 1 file changed, 92 insertions(+), 5 deletions(-) |
| |
| --- a/tools/testing/selftests/proc/proc-empty-vm.c~proc-test-proc-pid-statm |
| +++ a/tools/testing/selftests/proc/proc-empty-vm.c |
| @@ -303,6 +303,95 @@ static int test_proc_pid_smaps_rollup(pi |
| } |
| } |
| |
| +static const char *parse_u64(const char *p, const char *const end, uint64_t *rv) |
| +{ |
| + *rv = 0; |
| + for (; p != end; p += 1) { |
| + if ('0' <= *p && *p <= '9') { |
| + assert(!__builtin_mul_overflow(*rv, 10, rv)); |
| + assert(!__builtin_add_overflow(*rv, *p - '0', rv)); |
| + } else { |
| + break; |
| + } |
| + } |
| + assert(p != end); |
| + return p; |
| +} |
| + |
| +/* |
| + * There seems to be 2 types of valid output: |
| + * "0 A A B 0 0 0\n" for dynamic exeuctables, |
| + * "0 0 0 B 0 0 0\n" for static executables. |
| + */ |
| +static int test_proc_pid_statm(pid_t pid) |
| +{ |
| + char buf[4096]; |
| + snprintf(buf, sizeof(buf), "/proc/%u/statm", pid); |
| + int fd = open(buf, O_RDONLY); |
| + if (fd == -1) { |
| + perror("open /proc/${pid}/statm"); |
| + return EXIT_FAILURE; |
| + } |
| + |
| + ssize_t rv = read(fd, buf, sizeof(buf)); |
| + close(fd); |
| + |
| + assert(rv >= 0); |
| + assert(rv <= sizeof(buf)); |
| + if (0) { |
| + write(1, buf, rv); |
| + } |
| + |
| + const char *p = buf; |
| + const char *const end = p + rv; |
| + |
| + /* size */ |
| + assert(p != end && *p++ == '0'); |
| + assert(p != end && *p++ == ' '); |
| + |
| + uint64_t resident; |
| + p = parse_u64(p, end, &resident); |
| + assert(p != end && *p++ == ' '); |
| + |
| + uint64_t shared; |
| + p = parse_u64(p, end, &shared); |
| + assert(p != end && *p++ == ' '); |
| + |
| + uint64_t text; |
| + p = parse_u64(p, end, &text); |
| + assert(p != end && *p++ == ' '); |
| + |
| + assert(p != end && *p++ == '0'); |
| + assert(p != end && *p++ == ' '); |
| + |
| + /* data */ |
| + assert(p != end && *p++ == '0'); |
| + assert(p != end && *p++ == ' '); |
| + |
| + assert(p != end && *p++ == '0'); |
| + assert(p != end && *p++ == '\n'); |
| + |
| + assert(p == end); |
| + |
| + /* |
| + * "text" is "mm->end_code - mm->start_code" at execve(2) time. |
| + * munmap() doesn't change it. It can be anything (just link |
| + * statically). It can't be 0 because executing to this point |
| + * implies at least 1 page of code. |
| + */ |
| + assert(text > 0); |
| + |
| + /* |
| + * These two are always equal. Always 0 for statically linked |
| + * executables and sometimes 0 for dynamically linked executables. |
| + * There is no way to tell one from another without parsing ELF |
| + * which is too much for this test. |
| + */ |
| + assert(resident == shared); |
| + |
| + return EXIT_SUCCESS; |
| +} |
| + |
| int main(void) |
| { |
| int rv = EXIT_SUCCESS; |
| @@ -389,11 +478,9 @@ int main(void) |
| if (rv == EXIT_SUCCESS) { |
| rv = test_proc_pid_smaps_rollup(pid); |
| } |
| - /* |
| - * TODO test /proc/${pid}/statm, task_statm() |
| - * ->start_code, ->end_code aren't updated by munmap(). |
| - * Output can be "0 0 0 2 0 0 0\n" where "2" can be anything. |
| - */ |
| + if (rv == EXIT_SUCCESS) { |
| + rv = test_proc_pid_statm(pid); |
| + } |
| |
| /* Cut the rope. */ |
| int wstatus; |
| _ |