lkml.org 
[lkml]   [2017]   [May]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.11 076/197] IB/hfi1: Fix a subcontext memory leak
    Date
    4.11-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Michael J. Ruhl <michael.j.ruhl@intel.com>

    commit 224d71f910102c966cdcd782c97e096d5e26e4da upstream.

    The only context that frees user_exp_rcv data structures is the last
    context closed (from a sub-context set). This leaks the allocations
    from the other sub-contexts. Separate the common frees from the
    specific frees and call them at the appropriate time.

    Using KEDR to check for memory leaks we get:

    Before test:

    [leak_check] Possible leaks: 25

    After test:

    [leak_check] Possible leaks: 31 (6 leaked data structures)

    After patch applied (before and after test have the same value)

    [leak_check] Possible leaks: 25

    Each leak is 192 + 13440 + 6720 = 20352 bytes per sub-context.

    Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
    Signed-off-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
    Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
    Signed-off-by: Doug Ledford <dledford@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/infiniband/hw/hfi1/file_ops.c | 5 +++-
    drivers/infiniband/hw/hfi1/user_exp_rcv.c | 32 ++++++++++++++++--------------
    drivers/infiniband/hw/hfi1/user_exp_rcv.h | 1
    3 files changed, 23 insertions(+), 15 deletions(-)

    --- a/drivers/infiniband/hw/hfi1/file_ops.c
    +++ b/drivers/infiniband/hw/hfi1/file_ops.c
    @@ -752,6 +752,9 @@ static int hfi1_file_close(struct inode
    /* release the cpu */
    hfi1_put_proc_affinity(fdata->rec_cpu_num);

    + /* clean up rcv side */
    + hfi1_user_exp_rcv_free(fdata);
    +
    /*
    * Clear any left over, unhandled events so the next process that
    * gets this context doesn't get confused.
    @@ -791,7 +794,7 @@ static int hfi1_file_close(struct inode

    dd->rcd[uctxt->ctxt] = NULL;

    - hfi1_user_exp_rcv_free(fdata);
    + hfi1_user_exp_rcv_grp_free(uctxt);
    hfi1_clear_ctxt_pkey(dd, uctxt->ctxt);

    uctxt->rcvwait_to = 0;
    --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c
    +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
    @@ -251,36 +251,40 @@ done:
    return ret;
    }

    +void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt)
    +{
    + struct tid_group *grp, *gptr;
    +
    + list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list,
    + list) {
    + list_del_init(&grp->list);
    + kfree(grp);
    + }
    + hfi1_clear_tids(uctxt);
    +}
    +
    int hfi1_user_exp_rcv_free(struct hfi1_filedata *fd)
    {
    struct hfi1_ctxtdata *uctxt = fd->uctxt;
    - struct tid_group *grp, *gptr;

    - if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags))
    - return 0;
    /*
    * The notifier would have been removed when the process'es mm
    * was freed.
    */
    - if (fd->handler)
    + if (fd->handler) {
    hfi1_mmu_rb_unregister(fd->handler);
    -
    - kfree(fd->invalid_tids);
    -
    - if (!uctxt->cnt) {
    + } else {
    if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list))
    unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd);
    if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list))
    unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd);
    - list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list,
    - list) {
    - list_del_init(&grp->list);
    - kfree(grp);
    - }
    - hfi1_clear_tids(uctxt);
    }

    + kfree(fd->invalid_tids);
    + fd->invalid_tids = NULL;
    +
    kfree(fd->entry_to_rb);
    + fd->entry_to_rb = NULL;
    return 0;
    }

    --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h
    +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h
    @@ -70,6 +70,7 @@
    (tid) |= EXP_TID_SET(field, (value)); \
    } while (0)

    +void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt);
    int hfi1_user_exp_rcv_init(struct file *);
    int hfi1_user_exp_rcv_free(struct hfi1_filedata *);
    int hfi1_user_exp_rcv_setup(struct file *, struct hfi1_tid_info *);

    \
     
     \ /
      Last update: 2017-05-24 00:24    [W:3.207 / U:0.296 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site