On Sat, Feb 02, 2019 at 10:54:25PM -0800, Sandeep Patil wrote: > The 'pss_locked' field of smaps_rollup was being calculated incorrectly. > It accumulated the current pss everytime a locked VMA was found. Fix > that by adding to 'pss_locked' the same time as that of 'pss' if the vma > being walked is locked. > > Fixes: 493b0e9d945f ("mm: add /proc/pid/smaps_rollup") > Cc: stable@xxxxxxxxxxxxxxx # 4.14.y 4.19.y > Signed-off-by: Sandeep Patil <sspatil@xxxxxxxxxxx> > --- Reviewed-by: Joel Fernandes (Google) <joel@xxxxxxxxxxxxxxxxx> thanks, - Joel > > v1->v2 > ------ > - Move pss_locked accounting into smaps_account() inline with pss > > fs/proc/task_mmu.c | 22 ++++++++++++++-------- > 1 file changed, 14 insertions(+), 8 deletions(-) > > diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c > index f0ec9edab2f3..85b0ef890b28 100644 > --- a/fs/proc/task_mmu.c > +++ b/fs/proc/task_mmu.c > @@ -423,7 +423,7 @@ struct mem_size_stats { > }; > > static void smaps_account(struct mem_size_stats *mss, struct page *page, > - bool compound, bool young, bool dirty) > + bool compound, bool young, bool dirty, bool locked) > { > int i, nr = compound ? 1 << compound_order(page) : 1; > unsigned long size = nr * PAGE_SIZE; > @@ -450,24 +450,31 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page, > else > mss->private_clean += size; > mss->pss += (u64)size << PSS_SHIFT; > + if (locked) > + mss->pss_locked += (u64)size << PSS_SHIFT; > return; > } > > for (i = 0; i < nr; i++, page++) { > int mapcount = page_mapcount(page); > + unsigned long pss = (PAGE_SIZE << PSS_SHIFT); > > if (mapcount >= 2) { > if (dirty || PageDirty(page)) > mss->shared_dirty += PAGE_SIZE; > else > mss->shared_clean += PAGE_SIZE; > - mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount; > + mss->pss += pss / mapcount; > + if (locked) > + mss->pss_locked += pss / mapcount; > } else { > if (dirty || PageDirty(page)) > mss->private_dirty += PAGE_SIZE; > else > mss->private_clean += PAGE_SIZE; > - mss->pss += PAGE_SIZE << PSS_SHIFT; > + mss->pss += pss; > + if (locked) > + mss->pss_locked += pss; > } > } > } > @@ -490,6 +497,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, > { > struct mem_size_stats *mss = walk->private; > struct vm_area_struct *vma = walk->vma; > + bool locked = !!(vma->vm_flags & VM_LOCKED); > struct page *page = NULL; > > if (pte_present(*pte)) { > @@ -532,7 +540,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, > if (!page) > return; > > - smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte)); > + smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked); > } > > #ifdef CONFIG_TRANSPARENT_HUGEPAGE > @@ -541,6 +549,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, > { > struct mem_size_stats *mss = walk->private; > struct vm_area_struct *vma = walk->vma; > + bool locked = !!(vma->vm_flags & VM_LOCKED); > struct page *page; > > /* FOLL_DUMP will return -EFAULT on huge zero page */ > @@ -555,7 +564,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, > /* pass */; > else > VM_BUG_ON_PAGE(1, page); > - smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd)); > + smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked); > } > #else > static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, > @@ -737,11 +746,8 @@ static void smap_gather_stats(struct vm_area_struct *vma, > } > } > #endif > - > /* mmap_sem is held in m_start */ > walk_page_vma(vma, &smaps_walk); > - if (vma->vm_flags & VM_LOCKED) > - mss->pss_locked += mss->pss; > } > > #define SEQ_PUT_DEC(str, val) \ > -- > 2.20.1.611.gfbb209baf1-goog >