Skip to content

Commit

Permalink
mm: use maple tree operations for find_vma_intersection()
Browse files Browse the repository at this point in the history
Move find_vma_intersection() to mmap.c and change implementation to maple
tree.

When searching for a vma within a range, it is easier to use the maple
tree interface.

Exported find_vma_intersection() for kvm module.

Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
Signed-off-by: Alexandre Frade <kernel@xanmod.org>
  • Loading branch information
howlett authored and xanmod committed Oct 3, 2022
1 parent 1108eb0 commit 7976c7c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 18 deletions.
22 changes: 4 additions & 18 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2754,26 +2754,12 @@ extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long add
extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
struct vm_area_struct **pprev);

/**
* find_vma_intersection() - Look up the first VMA which intersects the interval
* @mm: The process address space.
* @start_addr: The inclusive start user address.
* @end_addr: The exclusive end user address.
*
* Returns: The first VMA within the provided range, %NULL otherwise. Assumes
* start_addr < end_addr.
/*
* Look up the first VMA which intersects the interval [start_addr, end_addr)
* NULL if none. Assume start_addr < end_addr.
*/
static inline
struct vm_area_struct *find_vma_intersection(struct mm_struct *mm,
unsigned long start_addr,
unsigned long end_addr)
{
struct vm_area_struct *vma = find_vma(mm, start_addr);

if (vma && end_addr <= vma->vm_start)
vma = NULL;
return vma;
}
unsigned long start_addr, unsigned long end_addr);

/**
* vma_lookup() - Find a VMA at a specific address
Expand Down
29 changes: 29 additions & 0 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,35 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,

EXPORT_SYMBOL(get_unmapped_area);

/**
* find_vma_intersection() - Look up the first VMA which intersects the interval
* @mm: The process address space.
* @start_addr: The inclusive start user address.
* @end_addr: The exclusive end user address.
*
* Returns: The first VMA within the provided range, %NULL otherwise. Assumes
* start_addr < end_addr.
*/
struct vm_area_struct *find_vma_intersection(struct mm_struct *mm,
unsigned long start_addr,
unsigned long end_addr)
{
struct vm_area_struct *vma;
unsigned long index = start_addr;

mmap_assert_locked(mm);
/* Check the cache first. */
vma = vmacache_find(mm, start_addr);
if (likely(vma))
return vma;

vma = mt_find(&mm->mm_mt, &index, end_addr - 1);
if (vma)
vmacache_update(start_addr, vma);
return vma;
}
EXPORT_SYMBOL(find_vma_intersection);

/**
* find_vma() - Find the VMA for a given address, or the next VMA.
* @mm: The mm_struct to check
Expand Down
11 changes: 11 additions & 0 deletions mm/nommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,17 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
vm_area_free(vma);
}

struct vm_area_struct *find_vma_intersection(struct mm_struct *mm,
unsigned long start_addr,
unsigned long end_addr)
{
unsigned long index = start_addr;

mmap_assert_locked(mm);
return mt_find(&mm->mm_mt, &index, end_addr - 1);
}
EXPORT_SYMBOL(find_vma_intersection);

/*
* look up the first VMA in which addr resides, NULL if none
* - should be called with mm->mmap_lock at least held readlocked
Expand Down

0 comments on commit 7976c7c

Please sign in to comment.