Merge tag 'nfs-for-4.9-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
[cascardo/linux.git] / net / sunrpc / xprtrdma / frwr_ops.c
index 892b5e1..2109495 100644 (file)
@@ -67,6 +67,8 @@
  * pending send queue WRs before the transport is reconnected.
  */
 
+#include <linux/sunrpc/rpc_rdma.h>
+
 #include "xprt_rdma.h"
 
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
@@ -161,7 +163,7 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r)
                return PTR_ERR(f->fr_mr);
        }
 
-       dprintk("RPC:       %s: recovered FRMR %p\n", __func__, r);
+       dprintk("RPC:       %s: recovered FRMR %p\n", __func__, f);
        f->fr_state = FRMR_IS_INVALID;
        return 0;
 }
@@ -242,9 +244,8 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
                                               depth;
        }
 
-       rpcrdma_set_max_header_sizes(ia, cdata, max_t(unsigned int, 1,
-                                                     RPCRDMA_MAX_DATA_SEGS /
-                                                     ia->ri_max_frmr_depth));
+       ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
+                               ia->ri_max_frmr_depth);
        return 0;
 }
 
@@ -329,7 +330,7 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
        frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
        if (wc->status != IB_WC_SUCCESS)
                __frwr_sendcompletion_flush(wc, frmr, "localinv");
-       complete_all(&frmr->fr_linv_done);
+       complete(&frmr->fr_linv_done);
 }
 
 /* Post a REG_MR Work Request to register a memory region
@@ -396,7 +397,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
                goto out_mapmr_err;
 
        dprintk("RPC:       %s: Using frmr %p to map %u segments (%u bytes)\n",
-               __func__, mw, mw->mw_nents, mr->length);
+               __func__, frmr, mw->mw_nents, mr->length);
 
        key = (u8)(mr->rkey & 0x000000FF);
        ib_update_fast_reg_key(mr, ++key);
@@ -449,6 +450,8 @@ __frwr_prepare_linv_wr(struct rpcrdma_mw *mw)
        struct rpcrdma_frmr *f = &mw->frmr;
        struct ib_send_wr *invalidate_wr;
 
+       dprintk("RPC:       %s: invalidating frmr %p\n", __func__, f);
+
        f->fr_state = FRMR_IS_INVALID;
        invalidate_wr = &f->fr_invwr;
 
@@ -472,6 +475,7 @@ static void
 frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
 {
        struct ib_send_wr *invalidate_wrs, *pos, *prev, *bad_wr;
+       struct rpcrdma_rep *rep = req->rl_reply;
        struct rpcrdma_ia *ia = &r_xprt->rx_ia;
        struct rpcrdma_mw *mw, *tmp;
        struct rpcrdma_frmr *f;
@@ -487,6 +491,12 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
        f = NULL;
        invalidate_wrs = pos = prev = NULL;
        list_for_each_entry(mw, &req->rl_registered, mw_list) {
+               if ((rep->rr_wc_flags & IB_WC_WITH_INVALIDATE) &&
+                   (mw->mw_handle == rep->rr_inv_rkey)) {
+                       mw->frmr.fr_state = FRMR_IS_INVALID;
+                       continue;
+               }
+
                pos = __frwr_prepare_linv_wr(mw);
 
                if (!invalidate_wrs)
@@ -496,6 +506,8 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
                prev = pos;
                f = &mw->frmr;
        }
+       if (!f)
+               goto unmap;
 
        /* Strong send queue ordering guarantees that when the
         * last WR in the chain completes, all WRs in the chain
@@ -510,6 +522,7 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
         * replaces the QP. The RPC reply handler won't call us
         * unless ri_id->qp is a valid pointer.
         */
+       r_xprt->rx_stats.local_inv_needed++;
        rc = ib_post_send(ia->ri_id->qp, invalidate_wrs, &bad_wr);
        if (rc)
                goto reset_mrs;
@@ -521,6 +534,8 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
         */
 unmap:
        list_for_each_entry_safe(mw, tmp, &req->rl_registered, mw_list) {
+               dprintk("RPC:       %s: unmapping frmr %p\n",
+                       __func__, &mw->frmr);
                list_del_init(&mw->mw_list);
                ib_dma_unmap_sg(ia->ri_device,
                                mw->mw_sg, mw->mw_nents, mw->mw_dir);
@@ -576,4 +591,5 @@ const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = {
        .ro_init_mr                     = frwr_op_init_mr,
        .ro_release_mr                  = frwr_op_release_mr,
        .ro_displayname                 = "frwr",
+       .ro_send_w_inv_ok               = RPCRDMA_CMP_F_SND_W_INV_OK,
 };