From: Matt Mackall <mpm@selenic.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 5/13] maps#2: Add callbacks for each level to page walker
Date: Fri, 06 Apr 2007 17:03:05 -0500 [thread overview]
Message-ID: <6.469046093@selenic.com> (raw)
In-Reply-To: <1.469046093@selenic.com>
Add callbacks for each level to page walker
This allows iterating over all levels of the page tables. Recursion
continues to the depth of the lowest supplied callback.
This makes the page walker nearly completely generic and should allow
it to replace some other hand-rolled page table walkers.
Signed-off-by: Matt Mackall <mpm@selenic.com>
Index: mm/fs/proc/task_mmu.c
===================================================================
--- mm.orig/fs/proc/task_mmu.c 2007-03-24 21:33:58.000000000 -0500
+++ mm/fs/proc/task_mmu.c 2007-03-24 21:34:07.000000000 -0500
@@ -280,10 +280,35 @@ static int clear_refs_pte_range(pmd_t *p
return 0;
}
+struct mm_walk {
+ int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *);
+ int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *);
+ int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *);
+ int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *);
+};
+
+static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ struct mm_walk *walk, void *private)
+{
+ pte_t *pte;
+ int err;
+
+ for (pte = pte_offset_map(pmd, addr); addr != end;
+ addr += PAGE_SIZE, pte++) {
+ if (pte_none(*pte))
+ continue;
+ err = walk->pte_entry(pte, addr, addr, private);
+ if (err) {
+ pte_unmap(pte);
+ return err;
+ }
+ }
+ pte_unmap(pte);
+ return 0;
+}
+
static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
- int (*action)(pmd_t *, unsigned long,
- unsigned long, void *),
- void *private)
+ struct mm_walk *walk, void *private)
{
pmd_t *pmd;
unsigned long next;
@@ -294,18 +319,22 @@ static int walk_pmd_range(pud_t *pud, un
next = pmd_addr_end(addr, end);
if (pmd_none_or_clear_bad(pmd))
continue;
- err = action(pmd, addr, next, private);
- if (err)
- return err;
+ if (walk->pmd_entry) {
+ err = walk->pmd_entry(pmd, addr, next, private);
+ if (err)
+ return err;
+ }
+ if (walk->pte_entry) {
+ err = walk_pte_range(pmd, addr, next, walk, private);
+ if (err)
+ return err;
+ }
}
-
return 0;
}
static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
- int (*action)(pmd_t *, unsigned long,
- unsigned long, void *),
- void *private)
+ struct mm_walk *walk, void *private)
{
pud_t *pud;
unsigned long next;
@@ -316,11 +345,17 @@ static int walk_pud_range(pgd_t *pgd, un
next = pud_addr_end(addr, end);
if (pud_none_or_clear_bad(pud))
continue;
- err = walk_pmd_range(pud, addr, next, action, private);
- if (err)
- return err;
+ if (walk->pud_entry) {
+ err = walk->pud_entry(pud, addr, next, private);
+ if (err)
+ return err;
+ }
+ if (walk->pmd_entry || walk->pte_entry) {
+ err = walk_pmd_range(pud, addr, next, walk, private);
+ if (err)
+ return err;
+ }
}
-
return 0;
}
@@ -337,9 +372,7 @@ static int walk_pud_range(pgd_t *pgd, un
*/
static int walk_page_range(struct mm_struct *mm,
unsigned long addr, unsigned long end,
- int (*action)(pmd_t *, unsigned long,
- unsigned long, void *),
- void *private)
+ struct mm_walk *walk, void *private)
{
pgd_t *pgd;
unsigned long next;
@@ -350,14 +383,22 @@ static int walk_page_range(struct mm_str
next = pgd_addr_end(addr, end);
if (pgd_none_or_clear_bad(pgd))
continue;
- err = walk_pud_range(pgd, addr, next, action, private);
- if (err)
- return err;
+ if (walk->pgd_entry) {
+ err = walk->pgd_entry(pgd, addr, next, private);
+ if (err)
+ return err;
+ }
+ if (walk->pud_entry || walk->pmd_entry || walk->pte_entry) {
+ err = walk_pud_range(pgd, addr, next, walk, private);
+ if (err)
+ return err;
+ }
}
-
return 0;
}
+static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range };
+
static int show_smap(struct seq_file *m, void *v)
{
struct vm_area_struct *vma = v;
@@ -367,10 +408,12 @@ static int show_smap(struct seq_file *m,
mss.vma = vma;
if (vma->vm_mm && !is_vm_hugetlb_page(vma))
walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
- smaps_pte_range, &mss);
+ &smaps_walk, &mss);
return show_map_internal(m, v, &mss);
}
+static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range };
+
void clear_refs_smap(struct mm_struct *mm)
{
struct vm_area_struct *vma;
@@ -379,7 +422,7 @@ void clear_refs_smap(struct mm_struct *m
for (vma = mm->mmap; vma; vma = vma->vm_next)
if (vma->vm_mm && !is_vm_hugetlb_page(vma))
walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
- clear_refs_pte_range, vma);
+ &clear_refs_walk, vma);
flush_tlb_mm(mm);
up_read(&mm->mmap_sem);
}
next prev parent reply other threads:[~2007-04-06 22:06 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-06 22:03 [PATCH 0/13] maps#2: pagemap, kpagemap, and related cleanups take 2 Matt Mackall
2007-04-06 22:03 ` [PATCH 1/13] maps#2: Uninline some functions in the page walker Matt Mackall
2007-04-06 22:03 ` [PATCH 2/13] maps#2: Eliminate the pmd_walker struct " Matt Mackall
2007-04-06 22:03 ` [PATCH 3/13] maps#2: Remove vma from args " Matt Mackall
2007-04-06 22:03 ` [PATCH 4/13] maps#2: Propagate errors from callback in " Matt Mackall
2007-04-06 22:03 ` Matt Mackall [this message]
2007-04-06 22:03 ` [PATCH 6/13] maps#2: Move the page walker code to lib/ Matt Mackall
2007-04-11 6:35 ` Nick Piggin
2007-04-11 7:17 ` Andrew Morton
2007-04-11 7:33 ` Nick Piggin
2007-04-11 14:40 ` Matt Mackall
2007-04-12 6:38 ` Nick Piggin
2007-04-17 20:45 ` Matt Mackall
2007-04-17 21:26 ` Permanent Kgdb integration into the kernel - lets get with it Jason Wessel
2007-04-17 22:09 ` Andi Kleen
2007-04-06 22:03 ` [PATCH 7/13] maps#2: Simplify interdependence of /proc/pid/maps and smaps Matt Mackall
2007-04-06 22:03 ` [PATCH 8/13] maps#2: Move clear_refs code to task_mmu.c Matt Mackall
2007-04-06 22:03 ` [PATCH 9/13] maps#2: Regroup task_mmu by interface Matt Mackall
2007-04-06 22:03 ` [PATCH 10/13] maps#2: Make /proc/pid/smaps optional under CONFIG_EMBEDDED Matt Mackall
2007-04-06 22:03 ` [PATCH 11/13] maps#2: Make /proc/pid/clear_refs option " Matt Mackall
2007-04-07 5:41 ` David Rientjes
2007-04-06 22:03 ` [PATCH 12/13] maps#2: Add /proc/pid/pagemap interface Matt Mackall
2007-04-07 6:55 ` Andrew Morton
2007-04-07 16:36 ` Matt Mackall
2007-04-19 19:12 ` Dave Hansen
2007-04-19 19:58 ` Matt Mackall
2007-04-06 22:03 ` [PATCH 13/13] maps#2: Add /proc/kpagemap interface Matt Mackall
2007-04-19 19:06 ` Dave Hansen
2007-04-19 20:02 ` Matt Mackall
2007-04-19 20:25 ` Dave Hansen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6.469046093@selenic.com \
--to=mpm@selenic.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).