IB/hfi1: Correctly compute node interval
authorMitko Haralanov <mitko.haralanov@intel.com>
Tue, 12 Apr 2016 17:46:41 +0000 (10:46 -0700)
committerDoug Ledford <dledford@redhat.com>
Thu, 28 Apr 2016 20:32:26 +0000 (16:32 -0400)
The computation of the interval of an interval RB node
was incorrect leading to data corruption due to the RB
search algorithm not properly finding the all RB nodes
in an MMU invalidation interval.

The problem stemmed from the fact that the beginning
address of the node's range was being aligned to a page
boundary. For certain buffer sizes, this would lead to
a end address calculation that was off by 1 page.

An important aspect of keeping the RB same is also
updating the node's range in the case it's being extended.

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>
drivers/staging/rdma/hfi1/mmu_rb.c
drivers/staging/rdma/hfi1/user_sdma.c

index 72b6d70ae2b57c5436984a17689bf61199881202..a1aaaeac4475dadd2b5862f826a72502bc8ef3cf 100644 (file)
@@ -91,7 +91,7 @@ static unsigned long mmu_node_start(struct mmu_rb_node *node)
 
 static unsigned long mmu_node_last(struct mmu_rb_node *node)
 {
-       return PAGE_ALIGN((node->addr & PAGE_MASK) + node->len) - 1;
+       return PAGE_ALIGN(node->addr + node->len) - 1;
 }
 
 int hfi1_mmu_rb_register(struct rb_root *root, struct mmu_rb_ops *ops)
index 044d33777fba0ebe1567a80856007be8d8251a93..d1645d98a43d5b2456e49ed244a7ebea9f965b95 100644 (file)
@@ -1076,7 +1076,6 @@ static int pin_vector_pages(struct user_sdma_request *req,
                        return -ENOMEM;
 
                node->rb.addr = (unsigned long)iovec->iov.iov_base;
-               node->rb.len = iovec->iov.iov_len;
                node->pq = pq;
                atomic_set(&node->refcount, 0);
                INIT_LIST_HEAD(&node->list);
@@ -1117,6 +1116,7 @@ retry:
                        goto bail;
                }
                kfree(node->pages);
+               node->rb.len = iovec->iov.iov_len;
                node->pages = pages;
                node->npages += pinned;
                npages = node->npages;