Merge branch 'llseek' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/bkl
[linux-2.6.git] / fs / proc / task_mmu.c
index caf0337..871e25e 100644 (file)
@@ -210,6 +210,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
        int flags = vma->vm_flags;
        unsigned long ino = 0;
        unsigned long long pgoff = 0;
+       unsigned long start;
        dev_t dev = 0;
        int len;
 
@@ -220,8 +221,14 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
                pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
        }
 
+       /* We don't show the stack guard page in /proc/maps */
+       start = vma->vm_start;
+       if (vma->vm_flags & VM_GROWSDOWN)
+               if (!vma_stack_continue(vma->vm_prev, vma->vm_start))
+                       start += PAGE_SIZE;
+
        seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
-                       vma->vm_start,
+                       start,
                        vma->vm_end,
                        flags & VM_READ ? 'r' : '-',
                        flags & VM_WRITE ? 'w' : '-',
@@ -247,25 +254,6 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
                                } else if (vma->vm_start <= mm->start_stack &&
                                           vma->vm_end >= mm->start_stack) {
                                        name = "[stack]";
-                               } else {
-                                       unsigned long stack_start;
-                                       struct proc_maps_private *pmp;
-
-                                       pmp = m->private;
-                                       stack_start = pmp->task->stack_start;
-
-                                       if (vma->vm_start <= stack_start &&
-                                           vma->vm_end >= stack_start) {
-                                               pad_len_spaces(m, len);
-                                               seq_printf(m,
-                                                "[threadstack:%08lx]",
-#ifdef CONFIG_STACK_GROWSUP
-                                                vma->vm_end - stack_start
-#else
-                                                stack_start - vma->vm_start
-#endif
-                                               );
-                                       }
                                }
                        } else {
                                name = "[vdso]";
@@ -375,13 +363,13 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                        mss->referenced += PAGE_SIZE;
                mapcount = page_mapcount(page);
                if (mapcount >= 2) {
-                       if (pte_dirty(ptent))
+                       if (pte_dirty(ptent) || PageDirty(page))
                                mss->shared_dirty += PAGE_SIZE;
                        else
                                mss->shared_clean += PAGE_SIZE;
                        mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
                } else {
-                       if (pte_dirty(ptent))
+                       if (pte_dirty(ptent) || PageDirty(page))
                                mss->private_dirty += PAGE_SIZE;
                        else
                                mss->private_clean += PAGE_SIZE;
@@ -551,6 +539,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 
 const struct file_operations proc_clear_refs_operations = {
        .write          = clear_refs_write,
+       .llseek         = noop_llseek,
 };
 
 struct pagemapread {
@@ -653,6 +642,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
        return err;
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
 static u64 huge_pte_to_pagemap_entry(pte_t pte, int offset)
 {
        u64 pme = 0;
@@ -662,31 +652,18 @@ static u64 huge_pte_to_pagemap_entry(pte_t pte, int offset)
        return pme;
 }
 
-static int pagemap_hugetlb_range(pte_t *pte, unsigned long addr,
-                                unsigned long end, struct mm_walk *walk)
+/* This function walks within one hugetlb entry in the single call */
+static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
+                                unsigned long addr, unsigned long end,
+                                struct mm_walk *walk)
 {
-       struct vm_area_struct *vma;
        struct pagemapread *pm = walk->private;
-       struct hstate *hs = NULL;
        int err = 0;
+       u64 pfn;
 
-       vma = find_vma(walk->mm, addr);
-       if (vma)
-               hs = hstate_vma(vma);
        for (; addr != end; addr += PAGE_SIZE) {
-               u64 pfn = PM_NOT_PRESENT;
-
-               if (vma && (addr >= vma->vm_end)) {
-                       vma = find_vma(walk->mm, addr);
-                       if (vma)
-                               hs = hstate_vma(vma);
-               }
-
-               if (vma && (vma->vm_start <= addr) && is_vm_hugetlb_page(vma)) {
-                       /* calculate pfn of the "raw" page in the hugepage. */
-                       int offset = (addr & ~huge_page_mask(hs)) >> PAGE_SHIFT;
-                       pfn = huge_pte_to_pagemap_entry(*pte, offset);
-               }
+               int offset = (addr & ~hmask) >> PAGE_SHIFT;
+               pfn = huge_pte_to_pagemap_entry(*pte, offset);
                err = add_to_pagemap(addr, pfn, pm);
                if (err)
                        return err;
@@ -696,6 +673,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long addr,
 
        return err;
 }
+#endif /* HUGETLB_PAGE */
 
 /*
  * /proc/pid/pagemap - an array mapping virtual pages to pfns
@@ -765,7 +743,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 
        pagemap_walk.pmd_entry = pagemap_pte_range;
        pagemap_walk.pte_hole = pagemap_pte_hole;
+#ifdef CONFIG_HUGETLB_PAGE
        pagemap_walk.hugetlb_entry = pagemap_hugetlb_range;
+#endif
        pagemap_walk.mm = mm;
        pagemap_walk.private = &pm;
 
@@ -800,7 +780,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
                start_vaddr = end;
 
                len = min(count, PM_ENTRY_BYTES * pm.pos);
-               if (copy_to_user(buf, pm.buffer, len) < 0) {
+               if (copy_to_user(buf, pm.buffer, len)) {
                        ret = -EFAULT;
                        goto out_free;
                }