lkml.org 
[lkml]   [2021]   [Aug]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 16/61] mm: Use maple tree operations for find_vma_intersection() and find_vma()
    Date
    From: "Liam R. Howlett" <Liam.Howlett@Oracle.com>

    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. This means the find_vma() call changes to a special
    case of the find_vma_intersection().

    Exported for kvm module.

    Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
    ---
    include/linux/mm.h | 25 ++++++-------------------
    mm/mmap.c | 38 ++++++++++++++++++++++++++++----------
    2 files changed, 34 insertions(+), 29 deletions(-)

    diff --git a/include/linux/mm.h b/include/linux/mm.h
    index a3086474d8d2..10763bd6fccb 100644
    --- a/include/linux/mm.h
    +++ b/include/linux/mm.h
    @@ -2774,26 +2774,13 @@ 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;
    -}
    +extern struct vm_area_struct *find_vma_intersection(struct mm_struct *mm,
    + unsigned long start_addr,
    + unsigned long end_addr);

    /**
    * vma_lookup() - Find a VMA at a specific address
    diff --git a/mm/mmap.c b/mm/mmap.c
    index 3d88fc87c289..9b86f47f7387 100644
    --- a/mm/mmap.c
    +++ b/mm/mmap.c
    @@ -2052,32 +2052,50 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
    EXPORT_SYMBOL(get_unmapped_area);

    /**
    - * find_vma() - Find the VMA for a given address, or the next vma.
    - * @mm: The mm_struct to check
    - * @addr: The address
    + * 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 VMA associated with addr, or the next vma.
    - * May return %NULL in the case of no vma at addr or above.
    + * Returns: The first VMA within the provided range, %NULL otherwise. Assumes
    + * start_addr < end_addr.
    */
    -struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long 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;
    - MA_STATE(mas, &mm->mm_mt, addr, addr);
    + MA_STATE(mas, &mm->mm_mt, start_addr, start_addr);

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

    rcu_read_lock();
    - vma = mas_find(&mas, -1);
    + vma = mas_find(&mas, end_addr - 1);
    rcu_read_unlock();
    if (vma)
    - vmacache_update(addr, vma);
    + vmacache_update(mas.index, 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
    + * @addr: The address
    + *
    + * Returns: The VMA associated with addr, or the next vma.
    + * May return NULL in the case of no vma at addr or above.
    + */
    +inline struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
    +{
    + // Note find_vma_intersection will decrease 0 to underflow to ULONG_MAX
    + return find_vma_intersection(mm, addr, 0);
    +}
    EXPORT_SYMBOL(find_vma);

    /**
    --
    2.30.2
    \
     
     \ /
      Last update: 2021-08-17 18:10    [W:4.403 / U:0.100 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site