IB/hfi1: Fix a subcontext memory leak
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. Cc: stable@vger.kernel.org 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>
This commit is contained in:
parent
94679061dc
commit
224d71f910
|
@ -756,6 +756,9 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
|
|||
/* 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.
|
||||
|
@ -795,7 +798,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
|
|||
|
||||
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;
|
||||
|
|
|
@ -252,36 +252,40 @@ int hfi1_user_exp_rcv_init(struct file *fp)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
Loading…
Reference in New Issue