diff options
author | Mitko Haralanov <mitko.haralanov@intel.com> | 2016-04-12 10:46:29 -0700 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-04-28 16:32:26 -0400 |
commit | 0ad2d3d05b4a597d1f2e239dcc6ab537cc3eeacb (patch) | |
tree | 06d2c25b74885670f776821b8b9447c6a0e9f9b4 /drivers/staging/rdma | |
parent | 4787bc5e1783e94f6b9518664609f3034dc799eb (diff) | |
download | linux-0ad2d3d05b4a597d1f2e239dcc6ab537cc3eeacb.tar.bz2 |
IB/hfi1: Fix memory leak in user ExpRcv and SDMA
The driver had two memory leaks - one in the user
expected receive code and one in SDMA buffer cache.
The leak in the expected receive code only showed up
when the user/admin had set ulimit sufficiently low
and the driver did not have enough room in the cache
before hitting the limit of allowed cachable memory.
When this condition occurred, the driver returned
early signaling userland that it needed to free some
buffers to free up room in the cache.
The bug was that the driver was not cleaning up
allocated memory prior to returning early.
The leak in the SDMA buffer cache could occur (even
though it never did), when the insertion of a buffer
node in the interval RB tree failed. In this case, the
driver failed to unpin the pages of the node instead
erroneously returning success.
Reviewed-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/staging/rdma')
-rw-r--r-- | drivers/staging/rdma/hfi1/user_exp_rcv.c | 7 | ||||
-rw-r--r-- | drivers/staging/rdma/hfi1/user_sdma.c | 3 |
2 files changed, 7 insertions, 3 deletions
diff --git a/drivers/staging/rdma/hfi1/user_exp_rcv.c b/drivers/staging/rdma/hfi1/user_exp_rcv.c index 8bd56d5c783d..1b640a35b3fe 100644 --- a/drivers/staging/rdma/hfi1/user_exp_rcv.c +++ b/drivers/staging/rdma/hfi1/user_exp_rcv.c @@ -399,8 +399,11 @@ int hfi1_user_exp_rcv_setup(struct file *fp, struct hfi1_tid_info *tinfo) * pages, accept the amount pinned so far and program only that. * User space knows how to deal with partially programmed buffers. */ - if (!hfi1_can_pin_pages(dd, fd->tid_n_pinned, npages)) - return -ENOMEM; + if (!hfi1_can_pin_pages(dd, fd->tid_n_pinned, npages)) { + ret = -ENOMEM; + goto bail; + } + pinned = hfi1_acquire_user_pages(vaddr, npages, true, pages); if (pinned <= 0) { ret = pinned; diff --git a/drivers/staging/rdma/hfi1/user_sdma.c b/drivers/staging/rdma/hfi1/user_sdma.c index 032949bac801..044d33777fba 100644 --- a/drivers/staging/rdma/hfi1/user_sdma.c +++ b/drivers/staging/rdma/hfi1/user_sdma.c @@ -1139,7 +1139,8 @@ retry: list_del(&node->list); pq->n_locked -= node->npages; spin_unlock(&pq->evict_lock); - ret = 0; + unpin_vector_pages(current->mm, node->pages, 0, + node->npages); goto bail; } } else { |