Table 1-1: Process specific entries in /proc 
 ..............................................................................
- File    Content                                        
- cmdline Command line arguments                         
- cpu    Current and last cpu in which it was executed          (2.4)(smp)
- cwd    Link to the current working directory
- environ Values of environment variables      
- exe    Link to the executable of this process
- fd      Directory, which contains all file descriptors 
- maps   Memory maps to executables and library files           (2.4)
- mem     Memory held by this process                    
- root   Link to the root directory of this process
- stat    Process status                                 
- statm   Process memory status information              
- status  Process status in human readable form          
- wchan   If CONFIG_KALLSYMS is set, a pre-decoded wchan
- smaps  Extension based on maps, presenting the rss size for each mapped file
+ File          Content
+ clear_refs    Clears page referenced bits shown in smaps output
+ cmdline       Command line arguments
+ cpu           Current and last cpu in which it was executed   (2.4)(smp)
+ cwd           Link to the current working directory
+ environ       Values of environment variables
+ exe           Link to the executable of this process
+ fd            Directory, which contains all file descriptors
+ maps          Memory maps to executables and library files    (2.4)
+ mem           Memory held by this process
+ root          Link to the root directory of this process
+ stat          Process status
+ statm         Process memory status information
+ status                Process status in human readable form
+ wchan         If CONFIG_KALLSYMS is set, a pre-decoded wchan
+ smaps         Extension based on maps, the rss size for each mapped file
 ..............................................................................
 
 For example, to get the status information of a process, all you have to do is
 
        .write          = oom_adjust_write,
 };
 
+static ssize_t clear_refs_write(struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF], *end;
+       struct mm_struct *mm;
+
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count))
+               return -EFAULT;
+       if (!simple_strtol(buffer, &end, 0))
+               return -EINVAL;
+       if (*end == '\n')
+               end++;
+       task = get_proc_task(file->f_path.dentry->d_inode);
+       if (!task)
+               return -ESRCH;
+       mm = get_task_mm(task);
+       if (mm) {
+               clear_refs_smap(mm);
+               mmput(mm);
+       }
+       put_task_struct(task);
+       if (end - buffer == 0)
+               return -EIO;
+       return end - buffer;
+}
+
+static struct file_operations proc_clear_refs_operations = {
+       .write          = clear_refs_write,
+};
+
 #ifdef CONFIG_AUDITSYSCALL
 #define TMPBUFLEN 21
 static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
        REG("mounts",     S_IRUGO, mounts),
        REG("mountstats", S_IRUSR, mountstats),
 #ifdef CONFIG_MMU
+       REG("clear_refs", S_IWUSR, clear_refs),
        REG("smaps",      S_IRUGO, smaps),
 #endif
 #ifdef CONFIG_SECURITY
        LNK("exe",       exe),
        REG("mounts",    S_IRUGO, mounts),
 #ifdef CONFIG_MMU
+       REG("clear_refs", S_IWUSR, clear_refs),
        REG("smaps",     S_IRUGO, smaps),
 #endif
 #ifdef CONFIG_SECURITY
 
                           "Shared_Dirty:   %8lu kB\n"
                           "Private_Clean:  %8lu kB\n"
                           "Private_Dirty:  %8lu kB\n"
-                          "Pgs_Referenced: %8lu kB\n",
+                          "Referenced:     %8lu kB\n",
                           (vma->vm_end - vma->vm_start) >> 10,
                           mss->resident >> 10,
                           mss->shared_clean  >> 10,
        return show_map_internal(m, v, NULL);
 }
 
-static void smaps_one_pmd(struct vm_area_struct *vma, pmd_t *pmd,
-                         unsigned long addr, unsigned long end,
-                         void *private)
+static void smaps_pte_range(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;
        cond_resched();
 }
 
-static inline void for_each_pmd_in_pud(struct pmd_walker *walker, pud_t *pud,
-                                      unsigned long addr, unsigned long end)
+static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+                                unsigned long addr, unsigned long end,
+                                void *private)
+{
+       pte_t *pte, ptent;
+       spinlock_t *ptl;
+       struct page *page;
+
+       pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+       for (; addr != end; pte++, addr += PAGE_SIZE) {
+               ptent = *pte;
+               if (!pte_present(ptent))
+                       continue;
+
+               page = vm_normal_page(vma, addr, ptent);
+               if (!page)
+                       continue;
+
+               /* Clear accessed and referenced bits. */
+               ptep_test_and_clear_young(vma, addr, pte);
+               ClearPageReferenced(page);
+       }
+       pte_unmap_unlock(pte - 1, ptl);
+       cond_resched();
+}
+
+static inline void walk_pmd_range(struct pmd_walker *walker, pud_t *pud,
+                                 unsigned long addr, unsigned long end)
 {
        pmd_t *pmd;
        unsigned long next;
        }
 }
 
-static inline void for_each_pud_in_pgd(struct pmd_walker *walker, pgd_t *pgd,
-                                      unsigned long addr, unsigned long end)
+static inline void walk_pud_range(struct pmd_walker *walker, pgd_t *pgd,
+                                 unsigned long addr, unsigned long end)
 {
        pud_t *pud;
        unsigned long next;
                next = pud_addr_end(addr, end);
                if (pud_none_or_clear_bad(pud))
                        continue;
-               for_each_pmd_in_pud(walker, pud, addr, next);
+               walk_pmd_range(walker, pud, addr, next);
        }
 }
 
-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)
+/*
+ * walk_page_range - walk the page tables of a VMA with a callback
+ * @vma - VMA to walk
+ * @action - callback invoked for every bottom-level (PTE) page table
+ * @private - private data passed to the callback function
+ *
+ * Recursively walk the page table for the memory area in a VMA, calling
+ * a callback for every bottom-level (PTE) page table.
+ */
+static inline void walk_page_range(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;
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
                        continue;
-               for_each_pud_in_pgd(&walker, pgd, addr, next);
+               walk_pud_range(&walker, pgd, addr, next);
        }
 }
 
 
        memset(&mss, 0, sizeof mss);
        if (vma->vm_mm && !is_vm_hugetlb_page(vma))
-               for_each_pmd(vma, smaps_one_pmd, &mss);
+               walk_page_range(vma, smaps_pte_range, &mss);
        return show_map_internal(m, v, &mss);
 }
 
+void clear_refs_smap(struct mm_struct *mm)
+{
+       struct vm_area_struct *vma;
+
+       down_read(&mm->mmap_sem);
+       for (vma = mm->mmap; vma; vma = vma->vm_next)
+               if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+                       walk_page_range(vma, clear_refs_pte_range, NULL);
+       flush_tlb_mm(mm);
+       up_read(&mm->mmap_sem);
+}
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
        struct proc_maps_private *priv = m->private;