diff options
author | KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> | 2012-01-10 18:08:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 19:30:44 -0500 |
commit | 6bd4837de96e7d9f9bf33e59117c24fc230862ac (patch) | |
tree | 633d23438e31aeef61063c6de490cc5696f4e5f5 /mm | |
parent | 948f017b093a9baac23855fcd920d3a970b71bb6 (diff) |
mm: simplify find_vma_prev()
commit 297c5eee37 ("mm: make the vma list be doubly linked") added the
vm_prev member to vm_area_struct. We can simplify find_vma_prev() by
using it. Also, this change helps to improve page fault performance
because it has stronger locality of reference.
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Shaohua Li <shaohua.li@intel.com>
Cc: Michal Hocko <mhocko@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/mmap.c | 36 |
1 files changed, 8 insertions, 28 deletions
@@ -1603,39 +1603,19 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) | |||
1603 | 1603 | ||
1604 | EXPORT_SYMBOL(find_vma); | 1604 | EXPORT_SYMBOL(find_vma); |
1605 | 1605 | ||
1606 | /* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ | 1606 | /* |
1607 | * Same as find_vma, but also return a pointer to the previous VMA in *pprev. | ||
1608 | * Note: pprev is set to NULL when return value is NULL. | ||
1609 | */ | ||
1607 | struct vm_area_struct * | 1610 | struct vm_area_struct * |
1608 | find_vma_prev(struct mm_struct *mm, unsigned long addr, | 1611 | find_vma_prev(struct mm_struct *mm, unsigned long addr, |
1609 | struct vm_area_struct **pprev) | 1612 | struct vm_area_struct **pprev) |
1610 | { | 1613 | { |
1611 | struct vm_area_struct *vma = NULL, *prev = NULL; | 1614 | struct vm_area_struct *vma; |
1612 | struct rb_node *rb_node; | ||
1613 | if (!mm) | ||
1614 | goto out; | ||
1615 | |||
1616 | /* Guard against addr being lower than the first VMA */ | ||
1617 | vma = mm->mmap; | ||
1618 | |||
1619 | /* Go through the RB tree quickly. */ | ||
1620 | rb_node = mm->mm_rb.rb_node; | ||
1621 | |||
1622 | while (rb_node) { | ||
1623 | struct vm_area_struct *vma_tmp; | ||
1624 | vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); | ||
1625 | |||
1626 | if (addr < vma_tmp->vm_end) { | ||
1627 | rb_node = rb_node->rb_left; | ||
1628 | } else { | ||
1629 | prev = vma_tmp; | ||
1630 | if (!prev->vm_next || (addr < prev->vm_next->vm_end)) | ||
1631 | break; | ||
1632 | rb_node = rb_node->rb_right; | ||
1633 | } | ||
1634 | } | ||
1635 | 1615 | ||
1636 | out: | 1616 | vma = find_vma(mm, addr); |
1637 | *pprev = prev; | 1617 | *pprev = vma ? vma->vm_prev : NULL; |
1638 | return prev ? prev->vm_next : vma; | 1618 | return vma; |
1639 | } | 1619 | } |
1640 | 1620 | ||
1641 | /* | 1621 | /* |