aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/task_mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/task_mmu.c')
-rw-r--r--fs/proc/task_mmu.c95
1 files changed, 17 insertions, 78 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 8952ce70315e..791b2d400be5 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -135,6 +135,7 @@ static void pad_len_spaces(struct seq_file *m, int len)
135 135
136struct mem_size_stats 136struct mem_size_stats
137{ 137{
138 struct vm_area_struct *vma;
138 unsigned long resident; 139 unsigned long resident;
139 unsigned long shared_clean; 140 unsigned long shared_clean;
140 unsigned long shared_dirty; 141 unsigned long shared_dirty;
@@ -144,13 +145,6 @@ struct mem_size_stats
144 u64 pss; 145 u64 pss;
145}; 146};
146 147
147struct pmd_walker {
148 struct vm_area_struct *vma;
149 void *private;
150 void (*action)(struct vm_area_struct *, pmd_t *, unsigned long,
151 unsigned long, void *);
152};
153
154static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss) 148static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
155{ 149{
156 struct proc_maps_private *priv = m->private; 150 struct proc_maps_private *priv = m->private;
@@ -240,11 +234,11 @@ static int show_map(struct seq_file *m, void *v)
240 return show_map_internal(m, v, NULL); 234 return show_map_internal(m, v, NULL);
241} 235}
242 236
243static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, 237static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
244 unsigned long addr, unsigned long end, 238 void *private)
245 void *private)
246{ 239{
247 struct mem_size_stats *mss = private; 240 struct mem_size_stats *mss = private;
241 struct vm_area_struct *vma = mss->vma;
248 pte_t *pte, ptent; 242 pte_t *pte, ptent;
249 spinlock_t *ptl; 243 spinlock_t *ptl;
250 struct page *page; 244 struct page *page;
@@ -282,12 +276,13 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
282 } 276 }
283 pte_unmap_unlock(pte - 1, ptl); 277 pte_unmap_unlock(pte - 1, ptl);
284 cond_resched(); 278 cond_resched();
279 return 0;
285} 280}
286 281
287static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd, 282static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
288 unsigned long addr, unsigned long end, 283 unsigned long end, void *private)
289 void *private)
290{ 284{
285 struct vm_area_struct *vma = private;
291 pte_t *pte, ptent; 286 pte_t *pte, ptent;
292 spinlock_t *ptl; 287 spinlock_t *ptl;
293 struct page *page; 288 struct page *page;
@@ -308,71 +303,10 @@ static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
308 } 303 }
309 pte_unmap_unlock(pte - 1, ptl); 304 pte_unmap_unlock(pte - 1, ptl);
310 cond_resched(); 305 cond_resched();
306 return 0;
311} 307}
312 308
313static inline void walk_pmd_range(struct pmd_walker *walker, pud_t *pud, 309static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range };
314 unsigned long addr, unsigned long end)
315{
316 pmd_t *pmd;
317 unsigned long next;
318
319 for (pmd = pmd_offset(pud, addr); addr != end;
320 pmd++, addr = next) {
321 next = pmd_addr_end(addr, end);
322 if (pmd_none_or_clear_bad(pmd))
323 continue;
324 walker->action(walker->vma, pmd, addr, next, walker->private);
325 }
326}
327
328static inline void walk_pud_range(struct pmd_walker *walker, pgd_t *pgd,
329 unsigned long addr, unsigned long end)
330{
331 pud_t *pud;
332 unsigned long next;
333
334 for (pud = pud_offset(pgd, addr); addr != end;
335 pud++, addr = next) {
336 next = pud_addr_end(addr, end);
337 if (pud_none_or_clear_bad(pud))
338 continue;
339 walk_pmd_range(walker, pud, addr, next);
340 }
341}
342
343/*
344 * walk_page_range - walk the page tables of a VMA with a callback
345 * @vma - VMA to walk
346 * @action - callback invoked for every bottom-level (PTE) page table
347 * @private - private data passed to the callback function
348 *
349 * Recursively walk the page table for the memory area in a VMA, calling
350 * a callback for every bottom-level (PTE) page table.
351 */
352static inline void walk_page_range(struct vm_area_struct *vma,
353 void (*action)(struct vm_area_struct *,
354 pmd_t *, unsigned long,
355 unsigned long, void *),
356 void *private)
357{
358 unsigned long addr = vma->vm_start;
359 unsigned long end = vma->vm_end;
360 struct pmd_walker walker = {
361 .vma = vma,
362 .private = private,
363 .action = action,
364 };
365 pgd_t *pgd;
366 unsigned long next;
367
368 for (pgd = pgd_offset(vma->vm_mm, addr); addr != end;
369 pgd++, addr = next) {
370 next = pgd_addr_end(addr, end);
371 if (pgd_none_or_clear_bad(pgd))
372 continue;
373 walk_pud_range(&walker, pgd, addr, next);
374 }
375}
376 310
377static int show_smap(struct seq_file *m, void *v) 311static int show_smap(struct seq_file *m, void *v)
378{ 312{
@@ -380,11 +314,15 @@ static int show_smap(struct seq_file *m, void *v)
380 struct mem_size_stats mss; 314 struct mem_size_stats mss;
381 315
382 memset(&mss, 0, sizeof mss); 316 memset(&mss, 0, sizeof mss);
317 mss.vma = vma;
383 if (vma->vm_mm && !is_vm_hugetlb_page(vma)) 318 if (vma->vm_mm && !is_vm_hugetlb_page(vma))
384 walk_page_range(vma, smaps_pte_range, &mss); 319 walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
320 &smaps_walk, &mss);
385 return show_map_internal(m, v, &mss); 321 return show_map_internal(m, v, &mss);
386} 322}
387 323
324static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range };
325
388void clear_refs_smap(struct mm_struct *mm) 326void clear_refs_smap(struct mm_struct *mm)
389{ 327{
390 struct vm_area_struct *vma; 328 struct vm_area_struct *vma;
@@ -392,7 +330,8 @@ void clear_refs_smap(struct mm_struct *mm)
392 down_read(&mm->mmap_sem); 330 down_read(&mm->mmap_sem);
393 for (vma = mm->mmap; vma; vma = vma->vm_next) 331 for (vma = mm->mmap; vma; vma = vma->vm_next)
394 if (vma->vm_mm && !is_vm_hugetlb_page(vma)) 332 if (vma->vm_mm && !is_vm_hugetlb_page(vma))
395 walk_page_range(vma, clear_refs_pte_range, NULL); 333 walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
334 &clear_refs_walk, vma);
396 flush_tlb_mm(mm); 335 flush_tlb_mm(mm);
397 up_read(&mm->mmap_sem); 336 up_read(&mm->mmap_sem);
398} 337}