Re: statm_pgd_range() sucks!

From: William Lee Irwin III (wli@holomorphy.com)
Date: Wed Sep 04 2002 - 22:20:35 EST


On Thu, Aug 29, 2002 at 07:51:44PM -0700, Andrew Morton wrote:
> BTW, Rohit's hugetlb patch touches proc_pid_statm(), so a diff on -mm3
> would be appreciated.

I lost track of what the TODO's were but this is of relatively minor
import, and I lagged long enough this is against 2.5.33-mm2:

Cheers,
Bill

--- linux-virgin/fs/proc/array.c.orig 2002-09-02 23:24:57.000000000 -0700
+++ linux-wli/fs/proc/array.c 2002-09-02 23:37:17.000000000 -0700
@@ -394,131 +394,38 @@
         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;
-
- 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();
-}
-
-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);
-}
+ int size, resident, shared, text, lib, data, dirty;
+ struct mm_struct *mm = get_task_mm(task);
+ struct vm_area_struct * vma;
 
-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++;
- }
-}
+ size = resident = shared = text = lib = data = dirty = 0;
 
-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);
+ if (!mm)
+ goto out;
 
- 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;
+ 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 (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)
+ 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);
 }
 
 /*
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 07 2002 - 22:00:23 EST