lkml.org 
[lkml]   [2011]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    SubjectRe: REGRESSION: Performance regressions from switching anon_vma->lock to mutex
    On Fri, Jun 17, 2011 at 11:32 AM, Peter Zijlstra <peterz@infradead.org> wrote:
    >
    > something like so I guess, completely untested etc..

    Having gone over it a bit more, I actually think I prefer to just
    special-case the allocation instead.

    We already have to drop the anon_vma lock for the "out of memory"
    case, and a slight re-organization of clone_anon_vma() makes it easy
    to just first try a NOIO allocation with the lock still held, and then
    if that fails do the "drop lock, retry, and hard-fail" case.

    IOW, something like the attached (on top of the patches already posted
    except for your memory reclaim thing)

    Hugh, does this fix the lockdep issue?

    Linus
    mm/rmap.c | 20 ++++++++++++--------
    1 files changed, 12 insertions(+), 8 deletions(-)

    diff --git a/mm/rmap.c b/mm/rmap.c
    index 68756a77ef87..27dfd3b82b0f 100644
    --- a/mm/rmap.c
    +++ b/mm/rmap.c
    @@ -112,9 +112,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma)
    kmem_cache_free(anon_vma_cachep, anon_vma);
    }

    -static inline struct anon_vma_chain *anon_vma_chain_alloc(void)
    +static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp)
    {
    - return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
    + return kmem_cache_alloc(anon_vma_chain_cachep, gfp);
    }

    static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
    @@ -159,7 +159,7 @@ int anon_vma_prepare(struct vm_area_struct *vma)
    struct mm_struct *mm = vma->vm_mm;
    struct anon_vma *allocated;

    - avc = anon_vma_chain_alloc();
    + avc = anon_vma_chain_alloc(GFP_KERNEL);
    if (!avc)
    goto out_enomem;

    @@ -253,9 +253,14 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
    list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
    struct anon_vma *anon_vma;

    - avc = anon_vma_chain_alloc();
    - if (!avc)
    - goto enomem_failure;
    + avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN);
    + if (unlikely(!avc)) {
    + unlock_anon_vma_root(root);
    + root = NULL;
    + avc = anon_vma_chain_alloc(GFP_KERNEL);
    + if (!avc)
    + goto enomem_failure;
    + }
    anon_vma = pavc->anon_vma;
    root = lock_anon_vma_root(root, anon_vma);
    anon_vma_chain_link(dst, avc, anon_vma);
    @@ -264,7 +269,6 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
    return 0;

    enomem_failure:
    - unlock_anon_vma_root(root);
    unlink_anon_vmas(dst);
    return -ENOMEM;
    }
    @@ -294,7 +298,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
    anon_vma = anon_vma_alloc();
    if (!anon_vma)
    goto out_error;
    - avc = anon_vma_chain_alloc();
    + avc = anon_vma_chain_alloc(GFP_KERNEL);
    if (!avc)
    goto out_error_free_anon_vma;
    \
     
     \ /
      Last update: 2011-06-17 20:43    [W:6.485 / U:1.408 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site