lkml.org 
[lkml]   [2014]   [Jul]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4/5] mm, shmem: Add shmem swap memory accounting
    Date
    Adds get_mm_shswap() which compute the size of swaped out shmem. It
    does so by pagewalking the mm and using the new shmem_locate() function
    to get the physical location of shmem pages.
    The result is displayed in the new VmShSw line of /proc/<pid>/status.
    Use mm_walk an shmem_locate() to account paged out shmem pages.

    It significantly slows down /proc/<pid>/status acccess speed when
    there is a big shmem mapping. If that is an issue, we can drop this
    patch and only display this counter in the inherently slower
    /proc/<pid>/smaps file (cf. next patch).

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

    diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
    index 1c49957..1a15c56 100644
    --- a/Documentation/filesystems/proc.txt
    +++ b/Documentation/filesystems/proc.txt
    @@ -172,6 +172,7 @@ read the file /proc/PID/status:
    VmPTE: 20 kb
    VmSwap: 0 kB
    VmShm: 0 kB
    + VmShSw: 0 kB
    Threads: 1
    SigQ: 0/28578
    SigPnd: 0000000000000000
    @@ -230,6 +231,7 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
    VmPTE size of page table entries
    VmSwap size of swap usage (the number of referred swapents)
    VmShm size of resident shmem memory
    + VmShSw size of paged out shmem memory
    Threads number of threads
    SigQ number of signals queued/max. number for queue
    SigPnd bitmap of pending signals for the thread
    diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
    index 4e60751..73f0ce4 100644
    --- a/fs/proc/task_mmu.c
    +++ b/fs/proc/task_mmu.c
    @@ -19,9 +19,80 @@
    #include <asm/tlbflush.h>
    #include "internal.h"

    +struct shswap_stats {
    + struct vm_area_struct *vma;
    + unsigned long shswap;
    +};
    +
    +#ifdef CONFIG_SHMEM
    +static int shswap_pte(pte_t *pte, unsigned long addr, unsigned long end,
    + struct mm_walk *walk)
    +{
    + struct shswap_stats *shss = walk->private;
    + struct vm_area_struct *vma = shss->vma;
    + pgoff_t pgoff = linear_page_index(vma, addr);
    + pte_t ptent = *pte;
    +
    + if (pte_none(ptent) &&
    + shmem_locate(vma, pgoff, NULL) == SHMEM_SWAP)
    + shss->shswap += end - addr;
    +
    + return 0;
    +}
    +
    +static int shswap_pte_hole(unsigned long addr, unsigned long end,
    + struct mm_walk *walk)
    +{
    + struct shswap_stats *shss = walk->private;
    + struct vm_area_struct *vma = shss->vma;
    + pgoff_t pgoff;
    +
    + for (; addr != end; addr += PAGE_SIZE) {
    + pgoff = linear_page_index(vma, addr);
    +
    + if (shmem_locate(vma, pgoff, NULL) == SHMEM_SWAP)
    + shss->shswap += PAGE_SIZE;
    + }
    +
    + return 0;
    +}
    +
    +static unsigned long get_mm_shswap(struct mm_struct *mm)
    +{
    + struct vm_area_struct *vma;
    + struct shswap_stats shss;
    + struct mm_walk shswap_walk = {
    + .pte_entry = shswap_pte,
    + .pte_hole = shswap_pte_hole,
    + .mm = mm,
    + .private = &shss,
    + };
    +
    + memset(&shss, 0, sizeof(shss));
    +
    + down_read(&mm->mmap_sem);
    + for (vma = mm->mmap; vma; vma = vma->vm_next)
    + if (shmem_vma(vma)) {
    + shss.vma = vma;
    + walk_page_range(vma->vm_start, vma->vm_end,
    + &shswap_walk);
    + }
    + up_read(&mm->mmap_sem);
    +
    + return shss.shswap;
    +}
    +
    +#else
    +
    +static unsigned long get_mm_shswap(struct mm_struct *mm)
    +{
    + return 0;
    +}
    +#endif
    +
    void task_mem(struct seq_file *m, struct mm_struct *mm)
    {
    - unsigned long data, text, lib, swap, shmem;
    + unsigned long data, text, lib, swap, shmem, shswap;
    unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;

    /*
    @@ -43,6 +114,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
    lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
    swap = get_mm_counter(mm, MM_SWAPENTS);
    shmem = get_mm_counter(mm, MM_SHMEMPAGES);
    + shswap = get_mm_shswap(mm);
    seq_printf(m,
    "VmPeak:\t%8lu kB\n"
    "VmSize:\t%8lu kB\n"
    @@ -56,7 +128,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
    "VmLib:\t%8lu kB\n"
    "VmPTE:\t%8lu kB\n"
    "VmSwap:\t%8lu kB\n"
    - "VmShm:\t%8lu kB\n",
    + "VmShm:\t%8lu kB\n"
    + "VmShSw:\t%8lu kB\n",
    hiwater_vm << (PAGE_SHIFT-10),
    total_vm << (PAGE_SHIFT-10),
    mm->locked_vm << (PAGE_SHIFT-10),
    @@ -68,7 +141,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
    (PTRS_PER_PTE * sizeof(pte_t) *
    atomic_long_read(&mm->nr_ptes)) >> 10,
    swap << (PAGE_SHIFT-10),
    - shmem << (PAGE_SHIFT-10));
    + shmem << (PAGE_SHIFT-10),
    + shswap >> 10);
    }

    unsigned long task_vsize(struct mm_struct *mm)
    --
    1.9.3


    \
     
     \ /
      Last update: 2014-07-22 16:21    [W:2.756 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site