xprtrdma: Remove assumption that each segment is <= PAGE_SIZE
authorTom Tucker <tom@ogc.us>
Mon, 20 Feb 2012 19:07:57 +0000 (13:07 -0600)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 21 Mar 2012 13:31:47 +0000 (09:31 -0400)
The xprtrdma FRMR mapping logic assumes that a segment is <= PAGE_SIZE.
This is not true for NFS4.

Signed-off-by: Tom Tucker <tom@ogc.us>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
net/sunrpc/xprtrdma/verbs.c

index 28236ba..745973b 100644 (file)
@@ -1490,6 +1490,9 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
        u8 key;
        int len, pageoff;
        int i, rc;
+       int seg_len;
+       u64 pa;
+       int page_no;
 
        pageoff = offset_in_page(seg1->mr_offset);
        seg1->mr_offset -= pageoff;     /* start of page */
@@ -1497,11 +1500,15 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
        len = -pageoff;
        if (*nsegs > RPCRDMA_MAX_DATA_SEGS)
                *nsegs = RPCRDMA_MAX_DATA_SEGS;
-       for (i = 0; i < *nsegs;) {
+       for (page_no = i = 0; i < *nsegs;) {
                rpcrdma_map_one(ia, seg, writing);
-               seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma;
+               pa = seg->mr_dma;
+               for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) {
+                       seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->
+                               page_list[page_no++] = pa;
+                       pa += PAGE_SIZE;
+               }
                len += seg->mr_len;
-               BUG_ON(seg->mr_len > PAGE_SIZE);
                ++seg;
                ++i;
                /* Check for holes */
@@ -1540,9 +1547,9 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
        frmr_wr.send_flags = IB_SEND_SIGNALED;
        frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma;
        frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl;
-       frmr_wr.wr.fast_reg.page_list_len = i;
+       frmr_wr.wr.fast_reg.page_list_len = page_no;
        frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
-       frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT;
+       frmr_wr.wr.fast_reg.length = page_no << PAGE_SHIFT;
        BUG_ON(frmr_wr.wr.fast_reg.length < len);
        frmr_wr.wr.fast_reg.access_flags = (writing ?
                                IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :