mm/smaps: fix shmem pte hole swap calculation

JIRA: https://issues.redhat.com/browse/RHEL-48221

This patch is a backport of the following upstream commit:
commit 10c848c8b4805ff026018bfb2b3dedd90e7b0cea
Author: Peter Xu <peterx@redhat.com>
Date:   Fri Nov 5 13:35:59 2021 -0700

    mm/smaps: fix shmem pte hole swap calculation

    Patch series "mm/smaps: Fixes and optimizations on shmem swap handling".

    This patch (of 3):

    The shmem swap calculation on the privately writable mappings are using
    wrong parameters as spotted by Vlastimil.  Fix them.  This was
    introduced in commit 48131e03ca ("mm, proc: reduce cost of
    /proc/pid/smaps for unpopulated shmem mappings"), when shmem_swap_usage
    was reworked to shmem_partial_swap_usage.

    Test program:

      void main(void)
      {
          char *buffer, *p;
          int i, fd;

          fd = memfd_create("test", 0);
          assert(fd > 0);

          /* isize==2M*3, fill in pages, swap them out */
          ftruncate(fd, SIZE_2M * 3);
          buffer = mmap(NULL, SIZE_2M * 3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
          assert(buffer);
          for (i = 0, p = buffer; i < SIZE_2M * 3 / 4096; i++) {
              *p = 1;
              p += 4096;
          }
          madvise(buffer, SIZE_2M * 3, MADV_PAGEOUT);
          munmap(buffer, SIZE_2M * 3);

          /*
           * Remap with private+writtable mappings on partial of the inode (<= 2M*3),
           * while the size must also be >= 2M*2 to make sure there's a none pmd so
           * smaps_pte_hole will be triggered.
           */
          buffer = mmap(NULL, SIZE_2M * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
          printf("pid=%d, buffer=%p\n", getpid(), buffer);

          /* Check /proc/$PID/smap_rollup, should see 4MB swap */
          sleep(1000000);
      }

    Before the patch, smaps_rollup shows <4MB swap and the number will be
    random depending on the alignment of the buffer of mmap() allocated.
    After this patch, it'll show 4MB.

    Link: https://lkml.kernel.org/r/20210917164756.8586-1-peterx@redhat.com
    Link: https://lkml.kernel.org/r/20210917164756.8586-2-peterx@redhat.com
    Fixes: 48131e03ca ("mm, proc: reduce cost of /proc/pid/smaps for unpopulated shmem mappings")
    Signed-off-by: Peter Xu <peterx@redhat.com>
    Reported-by: Vlastimil Babka <vbabka@suse.cz>
    Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: Matthew Wilcox <willy@infradead.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Signed-off-by: Rafael Aquini <aquini@redhat.com>
This commit is contained in:
Rafael Aquini 2024-07-16 09:29:07 -04:00
parent 416658c6f9
commit 1d8d66df11
1 changed files with 4 additions and 2 deletions

View File

@ -507,9 +507,11 @@ static int smaps_pte_hole(unsigned long addr, unsigned long end,
__always_unused int depth, struct mm_walk *walk)
{
struct mem_size_stats *mss = walk->private;
struct vm_area_struct *vma = walk->vma;
mss->swap += shmem_partial_swap_usage(
walk->vma->vm_file->f_mapping, addr, end);
mss->swap += shmem_partial_swap_usage(walk->vma->vm_file->f_mapping,
linear_page_index(vma, addr),
linear_page_index(vma, end));
return 0;
}