diff options
| author | Andrew Morton <akpm@digeo.com> | 2002-09-19 08:36:29 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-09-19 08:36:29 -0700 |
| commit | 6fda85f284986ede5458990e5b82115336d4f694 (patch) | |
| tree | 08e07684746832d0656938f6276f462ea8193dca /fs/proc/array.c | |
| parent | ccc98a67de98c912840e0a35a24115ad64ae426d (diff) | |
[PATCH] remove statm_pgd_range
Bill Irwin's patch to avoid having to walk pagetables while generating
/proc/stat output.
It can significantly overstate the size of various mappings because it
assumes that all VMAs are fully populated.
But spending 100% of one of my four CPUs running top(1) is a bug.
Bill says this fixes a bug, too. The `SIZE' parameter is supposed to
display the amount of memory which the process would consume if it
faulted everything in. But "before it only showed instantiated
3rd-level pagetables, so if something within a 4MB aligned range hadn't
been faulted in it would slip past the old one".
Diffstat (limited to 'fs/proc/array.c')
| -rw-r--r-- | fs/proc/array.c | 143 |
1 files changed, 26 insertions, 117 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index feb2cbab4699..c1587b0cc89b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -394,131 +394,40 @@ int proc_pid_stat(struct task_struct *task, char * buffer) return res; } -static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size, int * pages, int * shared, int * dirty, int * total) +int proc_pid_statm(task_t *task, char *buffer) { - unsigned long end, pmd_end; - pte_t *pte; - - if (pmd_none(*pmd)) - return; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); - return; - } - preempt_disable(); - pte = pte_offset_map(pmd, address); - end = address + size; - pmd_end = (address + PMD_SIZE) & PMD_MASK; - if (end > pmd_end) - end = pmd_end; - do { - pte_t page = *pte; - struct page *ptpage; - unsigned long pfn; + int size, resident, shared, text, lib, data, dirty; + struct mm_struct *mm = get_task_mm(task); + struct vm_area_struct * vma; - address += PAGE_SIZE; - pte++; - if (pte_none(page)) - continue; - ++*total; - if (!pte_present(page)) - continue; - pfn = pte_pfn(page); - if (!pfn_valid(pfn)) - continue; - ptpage = pfn_to_page(pfn); - if (PageReserved(ptpage)) - continue; - ++*pages; - if (pte_dirty(page)) - ++*dirty; - if (page_count(pte_page(page)) > 1) - ++*shared; - } while (address < end); - pte_unmap(pte - 1); - preempt_enable(); -} + size = resident = shared = text = lib = data = dirty = 0; -static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size, - int * pages, int * shared, int * dirty, int * total) -{ - pmd_t * pmd; - unsigned long end; - - if (pgd_none(*pgd)) - return; - if (pgd_bad(*pgd)) { - pgd_ERROR(*pgd); - pgd_clear(pgd); - return; - } - pmd = pmd_offset(pgd, address); - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - do { - statm_pte_range(pmd, address, end - address, pages, shared, dirty, total); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); -} - -static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end, - int * pages, int * shared, int * dirty, int * total) -{ - while (address < end) { - statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total); - address = (address + PGDIR_SIZE) & PGDIR_MASK; - pgd++; - } -} + if (!mm) + goto out; -int proc_pid_statm(struct task_struct *task, char * buffer) -{ - int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0; - struct mm_struct *mm = get_task_mm(task); + down_read(&mm->mmap_sem); + resident = mm->rss; + for (vma = mm->mmap; vma; vma = vma->vm_next) { + int pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - if (mm) { - struct vm_area_struct * vma; - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - pgd_t *pgd = pgd_offset(mm, vma->vm_start); - int pages = 0, shared = 0, dirty = 0, total = 0; - if (is_vm_hugetlb_page(vma)) { - int num_pages = ((vma->vm_end - vma->vm_start)/PAGE_SIZE); - - resident += num_pages; - if (!(vma->vm_flags & VM_DONTCOPY)) - share += num_pages; - if (vma->vm_flags & VM_WRITE) - dt += num_pages; - drs += num_pages; - vma = vma->vm_next; - continue; - } - statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total); - resident += pages; - share += shared; - dt += dirty; - size += total; - if (vma->vm_flags & VM_EXECUTABLE) - trs += pages; /* text */ - else if (vma->vm_flags & VM_GROWSDOWN) - drs += pages; /* stack */ - else if (vma->vm_end > 0x60000000) - lrs += pages; /* library */ - else - drs += pages; - vma = vma->vm_next; + size += pages; + if (is_vm_hugetlb_page(vma)) { + if (!(vma->vm_flags & VM_DONTCOPY)) + shared += pages; + continue; } - up_read(&mm->mmap_sem); - mmput(mm); + if (vma->vm_flags & VM_SHARED || !list_empty(&vma->shared)) + shared += pages; + if (vma->vm_flags & VM_EXECUTABLE) + text += pages; + else + data += pages; } + up_read(&mm->mmap_sem); + mmput(mm); +out: return sprintf(buffer,"%d %d %d %d %d %d %d\n", - size, resident, share, trs, lrs, drs, dt); + size, resident, shared, text, lib, data, dirty); } /* |
