fs/proc/task_mmu.c: add user-space support for resetting mm->hiwater_rss (peak RSS)
authorPetr Cermak <petrcermak@chromium.org>
Wed, 18 Feb 2015 10:39:10 +0000 (10:39 +0000)
committerStricted <info@stricted.net>
Thu, 11 Oct 2018 16:03:52 +0000 (18:03 +0200)
Peak resident size of a process can be reset back to the process's
current rss value by writing "5" to /proc/pid/clear_refs.  The driving
use-case for this would be getting the peak RSS value, which can be
retrieved from the VmHWM field in /proc/pid/status, per benchmark
iteration or test scenario.

Origin:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=695f055936938c674473ea071ca7359a863551e7

[akpm@linux-foundation.org: clarify behaviour in documentation]
Signed-off-by: Petr Cermak <petrcermak@chromium.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Primiano Tucci <primiano@chromium.org>
Cc: Petr Cermak <petrcermak@chromium.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Change-Id: I543a7640639d9916e813af875003fe3ee3a6bfe0

Documentation/filesystems/proc.txt
fs/proc/task_mmu.c
include/linux/mm.h

index 3cb829e6126482db4e949fad43c321124923f4db..80e34c4a5ec72a3a792cc805cd4a0117ac8ff176 100644 (file)
@@ -499,6 +499,10 @@ To clear the bits for the file mapped pages associated with the process
     > echo 3 > /proc/PID/clear_refs
 Any other value written to /proc/PID/clear_refs will have no effect.
 
+To reset the peak resident set size ("high water mark") to the process's
+current value:
+    > echo 5 > /proc/PID/clear_refs
+
 The /proc/pid/pagemap gives the PFN, which can be used to find the pageflags
 using /proc/kpageflags and number of times a page is mapped using
 /proc/kpagecount. For detailed explanation, see Documentation/vm/pagemap.txt.
index b13308334a460e00d7c3448bcb2b9decb2e56ccf..e3af617e05749072f0db64276bb7f43ef88f0829 100644 (file)
@@ -864,6 +864,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
 #define CLEAR_REFS_ALL 1
 #define CLEAR_REFS_ANON 2
 #define CLEAR_REFS_MAPPED 3
+#define CLEAR_REFS_MM_HIWATER_RSS 5
 
 static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
@@ -883,7 +884,8 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
        rv = kstrtoint(strstrip(buffer), 10, &type);
        if (rv < 0)
                return rv;
-       if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED)
+       if ((type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED) &&
+           type != CLEAR_REFS_MM_HIWATER_RSS)
                return -EINVAL;
        task = get_proc_task(file_inode(file));
        if (!task)
@@ -894,6 +896,18 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                        .pmd_entry = clear_refs_pte_range,
                        .mm = mm,
                };
+
+               if (type == CLEAR_REFS_MM_HIWATER_RSS) {
+                       /*
+                        * Writing 5 to /proc/pid/clear_refs resets the peak
+                        * resident set size to this mm's current rss value.
+                        */
+                       down_write(&mm->mmap_sem);
+                       reset_mm_hiwater_rss(mm);
+                       up_write(&mm->mmap_sem);
+                       goto out_mm;
+               }
+
                down_read(&mm->mmap_sem);
                for (vma = mm->mmap; vma; vma = vma->vm_next) {
                        clear_refs_walk.private = vma;
@@ -917,6 +931,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                }
                flush_tlb_mm(mm);
                up_read(&mm->mmap_sem);
+out_mm:
                mmput(mm);
        }
        put_task_struct(task);
index 4612a39457a8b9500366da64f34452220dbbc3e0..0d0b53de1eb230cd9211776a4643c1e526bf6c9e 100644 (file)
@@ -1165,6 +1165,11 @@ static inline void update_hiwater_vm(struct mm_struct *mm)
                mm->hiwater_vm = mm->total_vm;
 }
 
+static inline void reset_mm_hiwater_rss(struct mm_struct *mm)
+{
+       mm->hiwater_rss = get_mm_rss(mm);
+}
+
 static inline void setmax_mm_hiwater_rss(unsigned long *maxrss,
                                         struct mm_struct *mm)
 {