]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/proc/task_mmu.c
smaps: add pages referenced count to smaps
[linux-2.6-omap-h63xx.git] / fs / proc / task_mmu.c
index 6b769afac55a18ff274ef8ed90b2d0510a86804b..199088ee969b1ec956fb85337e614c9ec42c92ab 100644 (file)
@@ -94,8 +94,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
        }
 
        if (vma) {
-               *mnt = mntget(vma->vm_file->f_vfsmnt);
-               *dentry = dget(vma->vm_file->f_dentry);
+               *mnt = mntget(vma->vm_file->f_path.mnt);
+               *dentry = dget(vma->vm_file->f_path.dentry);
                result = 0;
        }
 
@@ -120,6 +120,14 @@ struct mem_size_stats
        unsigned long shared_dirty;
        unsigned long private_clean;
        unsigned long private_dirty;
+       unsigned long referenced;
+};
+
+struct pmd_walker {
+       struct vm_area_struct *vma;
+       void *private;
+       void (*action)(struct vm_area_struct *, pmd_t *, unsigned long,
+                      unsigned long, void *);
 };
 
 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
@@ -135,7 +143,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
        int len;
 
        if (file) {
-               struct inode *inode = vma->vm_file->f_dentry->d_inode;
+               struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
                dev = inode->i_sb->s_dev;
                ino = inode->i_ino;
        }
@@ -156,7 +164,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
         */
        if (file) {
                pad_len_spaces(m, len);
-               seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
+               seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n");
        } else {
                const char *name = arch_vma_name(vma);
                if (!name) {
@@ -181,18 +189,20 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
 
        if (mss)
                seq_printf(m,
-                          "Size:          %8lu kB\n"
-                          "Rss:           %8lu kB\n"
-                          "Shared_Clean:  %8lu kB\n"
-                          "Shared_Dirty:  %8lu kB\n"
-                          "Private_Clean: %8lu kB\n"
-                          "Private_Dirty: %8lu kB\n",
+                          "Size:           %8lu kB\n"
+                          "Rss:            %8lu kB\n"
+                          "Shared_Clean:   %8lu kB\n"
+                          "Shared_Dirty:   %8lu kB\n"
+                          "Private_Clean:  %8lu kB\n"
+                          "Private_Dirty:  %8lu kB\n"
+                          "Pgs_Referenced: %8lu kB\n",
                           (vma->vm_end - vma->vm_start) >> 10,
                           mss->resident >> 10,
                           mss->shared_clean  >> 10,
                           mss->shared_dirty  >> 10,
                           mss->private_clean >> 10,
-                          mss->private_dirty >> 10);
+                          mss->private_dirty >> 10,
+                          mss->referenced >> 10);
 
        if (m->count < m->size)  /* vma is copied successfully */
                m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
@@ -204,16 +214,17 @@ static int show_map(struct seq_file *m, void *v)
        return show_map_internal(m, v, NULL);
 }
 
-static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+static void smaps_one_pmd(struct vm_area_struct *vma, pmd_t *pmd,
+                         unsigned long addr, unsigned long end,
+                         void *private)
 {
+       struct mem_size_stats *mss = private;
        pte_t *pte, ptent;
        spinlock_t *ptl;
        struct page *page;
 
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-       do {
+       for (; addr != end; pte++, addr += PAGE_SIZE) {
                ptent = *pte;
                if (!pte_present(ptent))
                        continue;
@@ -224,6 +235,9 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                if (!page)
                        continue;
 
+               /* Accumulate the size in pages that have been accessed. */
+               if (pte_young(ptent) || PageReferenced(page))
+                       mss->referenced += PAGE_SIZE;
                if (page_mapcount(page) >= 2) {
                        if (pte_dirty(ptent))
                                mss->shared_dirty += PAGE_SIZE;
@@ -235,57 +249,64 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        else
                                mss->private_clean += PAGE_SIZE;
                }
-       } while (pte++, addr += PAGE_SIZE, addr != end);
+       }
        pte_unmap_unlock(pte - 1, ptl);
        cond_resched();
 }
 
-static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+static inline void for_each_pmd_in_pud(struct pmd_walker *walker, pud_t *pud,
+                                      unsigned long addr, unsigned long end)
 {
        pmd_t *pmd;
        unsigned long next;
 
-       pmd = pmd_offset(pud, addr);
-       do {
+       for (pmd = pmd_offset(pud, addr); addr != end;
+            pmd++, addr = next) {
                next = pmd_addr_end(addr, end);
                if (pmd_none_or_clear_bad(pmd))
                        continue;
-               smaps_pte_range(vma, pmd, addr, next, mss);
-       } while (pmd++, addr = next, addr != end);
+               walker->action(walker->vma, pmd, addr, next, walker->private);
+       }
 }
 
-static inline void smaps_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+static inline void for_each_pud_in_pgd(struct pmd_walker *walker, pgd_t *pgd,
+                                      unsigned long addr, unsigned long end)
 {
        pud_t *pud;
        unsigned long next;
 
-       pud = pud_offset(pgd, addr);
-       do {
+       for (pud = pud_offset(pgd, addr); addr != end;
+            pud++, addr = next) {
                next = pud_addr_end(addr, end);
                if (pud_none_or_clear_bad(pud))
                        continue;
-               smaps_pmd_range(vma, pud, addr, next, mss);
-       } while (pud++, addr = next, addr != end);
+               for_each_pmd_in_pud(walker, pud, addr, next);
+       }
 }
 
-static inline void smaps_pgd_range(struct vm_area_struct *vma,
-                               unsigned long addr, unsigned long end,
-                               struct mem_size_stats *mss)
+static inline void for_each_pmd(struct vm_area_struct *vma,
+                               void (*action)(struct vm_area_struct *, pmd_t *,
+                                              unsigned long, unsigned long,
+                                              void *),
+                               void *private)
 {
+       unsigned long addr = vma->vm_start;
+       unsigned long end = vma->vm_end;
+       struct pmd_walker walker = {
+               .vma            = vma,
+               .private        = private,
+               .action         = action,
+       };
        pgd_t *pgd;
        unsigned long next;
 
-       pgd = pgd_offset(vma->vm_mm, addr);
-       do {
+       for (pgd = pgd_offset(vma->vm_mm, addr); addr != end;
+            pgd++, addr = next) {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
                        continue;
-               smaps_pud_range(vma, pgd, addr, next, mss);
-       } while (pgd++, addr = next, addr != end);
+               for_each_pud_in_pgd(&walker, pgd, addr, next);
+       }
 }
 
 static int show_smap(struct seq_file *m, void *v)
@@ -295,7 +316,7 @@ static int show_smap(struct seq_file *m, void *v)
 
        memset(&mss, 0, sizeof mss);
        if (vma->vm_mm && !is_vm_hugetlb_page(vma))
-               smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss);
+               for_each_pmd(vma, smaps_one_pmd, &mss);
        return show_map_internal(m, v, &mss);
 }
 
@@ -434,7 +455,7 @@ static int maps_open(struct inode *inode, struct file *file)
        return do_maps_open(inode, file, &proc_pid_maps_op);
 }
 
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
        .open           = maps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -456,7 +477,7 @@ static int numa_maps_open(struct inode *inode, struct file *file)
        return do_maps_open(inode, file, &proc_pid_numa_maps_op);
 }
 
-struct file_operations proc_numa_maps_operations = {
+const struct file_operations proc_numa_maps_operations = {
        .open           = numa_maps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -469,7 +490,7 @@ static int smaps_open(struct inode *inode, struct file *file)
        return do_maps_open(inode, file, &proc_pid_smaps_op);
 }
 
-struct file_operations proc_smaps_operations = {
+const struct file_operations proc_smaps_operations = {
        .open           = smaps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,