IB/qib: Convert qib_user_sdma_pin_pages() to use get_user_pages_fast()
PATCH 1/1 IB/qib: Convert qib_user_sdma_pin_pages() to use get_user_pages_fast()
From: Jan Kara <[email protected]>
commit 603e7729920e42b3c2f4dbfab9eef4878cb6e8fa upstream.
qib_user_sdma_queue_pkts() gets called with mmap_sem held for writing. Except for get_user_pages() deep down in qib_user_sdma_pin_pages() we don't seem to need mmap_sem at all. Even more interestingly the function qib_user_sdma_queue_pkts() (and also qib_user_sdma_coalesce() called somewhat later) call copy_from_user() which can hit a page fault and we deadlock on trying to get mmap_sem when handling that fault.
So just make qib_user_sdma_pin_pages() use get_user_pages_fast() and leave mmap_sem locking for mm.
This deadlock has actually been observed in the wild when the node is under memory pressure.
Patch for v3.4.
[Backported to 3.4: (Thank to Ben Hutchings)
- Adjust context
- Adjust indentation and nr_pages argument in qib_user_sdma_pin_pages()]
--- drivers/infiniband/hw/qib/qib_user_sdma.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/infiniband/hw/qib/qib_user_sdma.c +1 -5
@@ -284,8 +284,7 @@ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd,int j;int ret; - ret =get_user_pages (current, current->mm, addr, - npages,0 ,1 , pages,NULL ); + ret =get_user_pages_fast (addr, npages,0 , pages);if (ret != npages) {int i;
@@ -830,10 +829,7 @@ int qib_user_sdma_writev(struct qib_ctxtdata *rcd,while (dim) {const int mxp =8 ; -down_write (¤t->mm->mmap_sem); ret =qib_user_sdma_queue_pkts (dd, pq, &list, iov, dim, mxp); -up_write (¤t->mm->mmap_sem); -if (ret <=0 ) goto done_unlock;else {
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html