aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMitko Haralanov <mitko.haralanov@intel.com>2016-04-12 13:46:16 -0400
committerDoug Ledford <dledford@redhat.com>2016-04-28 12:00:38 -0400
commit849e3e9398608c26a7c54bf9fbf3288f7ced6bfb (patch)
tree77ebe0377b3d1a6f968fc1468b7f201fcb36e275
parentde82bdff62a9078a6e4f1452e2f2604686e51e49 (diff)
IB/hfi1: Prevent unpinning of wrong pages
The routine used by the SDMA cache to handle already cached nodes can extend an already existing node. In its error handling code, the routine will unpin pages when not all pages of the buffer extension were pinned. There was a bug in that part of the routine, which would mistakenly unpin pages from the original set rather than the newly pinned pages. This commit fixes that bug by offsetting the page array to the proper place pointing at the beginning of the newly pinned pages. 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>
-rw-r--r--drivers/staging/rdma/hfi1/user_sdma.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/staging/rdma/hfi1/user_sdma.c b/drivers/staging/rdma/hfi1/user_sdma.c
index e08c74fe4c6b..d53a659548e0 100644
--- a/drivers/staging/rdma/hfi1/user_sdma.c
+++ b/drivers/staging/rdma/hfi1/user_sdma.c
@@ -278,7 +278,8 @@ static inline void pq_update(struct hfi1_user_sdma_pkt_q *);
278static void user_sdma_free_request(struct user_sdma_request *, bool); 278static void user_sdma_free_request(struct user_sdma_request *, bool);
279static int pin_vector_pages(struct user_sdma_request *, 279static int pin_vector_pages(struct user_sdma_request *,
280 struct user_sdma_iovec *); 280 struct user_sdma_iovec *);
281static void unpin_vector_pages(struct mm_struct *, struct page **, unsigned); 281static void unpin_vector_pages(struct mm_struct *, struct page **, unsigned,
282 unsigned);
282static int check_header_template(struct user_sdma_request *, 283static int check_header_template(struct user_sdma_request *,
283 struct hfi1_pkt_header *, u32, u32); 284 struct hfi1_pkt_header *, u32, u32);
284static int set_txreq_header(struct user_sdma_request *, 285static int set_txreq_header(struct user_sdma_request *,
@@ -1110,7 +1111,8 @@ retry:
1110 goto bail; 1111 goto bail;
1111 } 1112 }
1112 if (pinned != npages) { 1113 if (pinned != npages) {
1113 unpin_vector_pages(current->mm, pages, pinned); 1114 unpin_vector_pages(current->mm, pages, node->npages,
1115 pinned);
1114 ret = -EFAULT; 1116 ret = -EFAULT;
1115 goto bail; 1117 goto bail;
1116 } 1118 }
@@ -1150,9 +1152,9 @@ bail:
1150} 1152}
1151 1153
1152static void unpin_vector_pages(struct mm_struct *mm, struct page **pages, 1154static void unpin_vector_pages(struct mm_struct *mm, struct page **pages,
1153 unsigned npages) 1155 unsigned start, unsigned npages)
1154{ 1156{
1155 hfi1_release_user_pages(mm, pages, npages, 0); 1157 hfi1_release_user_pages(mm, pages + start, npages, 0);
1156 kfree(pages); 1158 kfree(pages);
1157} 1159}
1158 1160
@@ -1566,7 +1568,8 @@ static void sdma_rb_remove(struct rb_root *root, struct mmu_rb_node *mnode,
1566 * prevent a deadlock when hfi1_release_user_pages() attempts to 1568 * prevent a deadlock when hfi1_release_user_pages() attempts to
1567 * take the mmap_sem, which the MMU notifier has already taken. 1569 * take the mmap_sem, which the MMU notifier has already taken.
1568 */ 1570 */
1569 unpin_vector_pages(mm ? NULL : current->mm, node->pages, node->npages); 1571 unpin_vector_pages(mm ? NULL : current->mm, node->pages, 0,
1572 node->npages);
1570 /* 1573 /*
1571 * If called by the MMU notifier, we have to adjust the pinned 1574 * If called by the MMU notifier, we have to adjust the pinned
1572 * page count ourselves. 1575 * page count ourselves.