]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sunrpc/xprtrdma/verbs.c
xprtrdma: Make sendctx queue lifetime the same as connection lifetime
[linux.git] / net / sunrpc / xprtrdma / verbs.c
index 3a56458e8c056ff10a9c81daa06566e895916e7f..b6aba0c859988762fc3a1805bff01ad97e17de79 100644 (file)
 /*
  * internal functions
  */
+static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt);
+static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,
                                       struct rpcrdma_sendctx *sc);
 static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt);
-static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf);
+static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt);
 static struct rpcrdma_regbuf *
@@ -244,6 +246,7 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                        ia->ri_id->device->name,
                        rpcrdma_addrstr(r_xprt), rpcrdma_portstr(r_xprt));
 #endif
+               init_completion(&ia->ri_remove_done);
                set_bit(RPCRDMA_IAF_REMOVING, &ia->ri_flags);
                ep->rep_connected = -ENODEV;
                xprt_force_disconnect(xprt);
@@ -297,7 +300,6 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rpcrdma_ia *ia)
        int rc;
 
        init_completion(&ia->ri_done);
-       init_completion(&ia->ri_remove_done);
 
        id = rdma_create_id(xprt->rx_xprt.xprt_net, rpcrdma_cm_event_handler,
                            xprt, RDMA_PS_TCP, IB_QPT_RC);
@@ -421,13 +423,14 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
        /* The ULP is responsible for ensuring all DMA
         * mappings and MRs are gone.
         */
-       rpcrdma_reps_destroy(buf);
+       rpcrdma_reps_unmap(r_xprt);
        list_for_each_entry(req, &buf->rb_allreqs, rl_all) {
                rpcrdma_regbuf_dma_unmap(req->rl_rdmabuf);
                rpcrdma_regbuf_dma_unmap(req->rl_sendbuf);
                rpcrdma_regbuf_dma_unmap(req->rl_recvbuf);
        }
        rpcrdma_mrs_destroy(r_xprt);
+       rpcrdma_sendctxs_destroy(r_xprt);
        ib_dealloc_pd(ia->ri_pd);
        ia->ri_pd = NULL;
 
@@ -470,21 +473,12 @@ int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
        struct rpcrdma_ia *ia = &r_xprt->rx_ia;
        struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
        struct ib_cq *sendcq, *recvcq;
-       unsigned int max_sge;
        int rc;
 
        ep->rep_max_requests = xprt_rdma_slot_table_entries;
        ep->rep_inline_send = xprt_rdma_max_inline_write;
        ep->rep_inline_recv = xprt_rdma_max_inline_read;
 
-       max_sge = min_t(unsigned int, ia->ri_id->device->attrs.max_send_sge,
-                       RPCRDMA_MAX_SEND_SGES);
-       if (max_sge < RPCRDMA_MIN_SEND_SGES) {
-               pr_warn("rpcrdma: HCA provides only %d send SGEs\n", max_sge);
-               return -ENOMEM;
-       }
-       ia->ri_max_send_sges = max_sge;
-
        rc = frwr_open(ia, ep);
        if (rc)
                return rc;
@@ -492,8 +486,6 @@ int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
        ep->rep_attr.event_handler = rpcrdma_qp_event_handler;
        ep->rep_attr.qp_context = ep;
        ep->rep_attr.srq = NULL;
-       ep->rep_attr.cap.max_send_sge = max_sge;
-       ep->rep_attr.cap.max_recv_sge = 1;
        ep->rep_attr.cap.max_inline_data = 0;
        ep->rep_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
        ep->rep_attr.qp_type = IB_QPT_RC;
@@ -716,6 +708,10 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
        rpcrdma_reset_cwnd(r_xprt);
        rpcrdma_post_recvs(r_xprt, true);
 
+       rc = rpcrdma_sendctxs_create(r_xprt);
+       if (rc)
+               goto out;
+
        rc = rdma_connect(ia->ri_id, &ep->rep_remote_cma);
        if (rc)
                goto out;
@@ -768,6 +764,7 @@ rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
        rpcrdma_xprt_drain(r_xprt);
        rpcrdma_reqs_reset(r_xprt);
        rpcrdma_mrs_destroy(r_xprt);
+       rpcrdma_sendctxs_destroy(r_xprt);
 }
 
 /* Fixed-size circular FIFO queue. This implementation is wait-free and
@@ -787,20 +784,24 @@ rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
  * queue activity, and rpcrdma_xprt_drain has flushed all remaining
  * Send requests.
  */
-static void rpcrdma_sendctxs_destroy(struct rpcrdma_buffer *buf)
+static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt)
 {
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
        unsigned long i;
 
+       if (!buf->rb_sc_ctxs)
+               return;
        for (i = 0; i <= buf->rb_sc_last; i++)
                kfree(buf->rb_sc_ctxs[i]);
        kfree(buf->rb_sc_ctxs);
+       buf->rb_sc_ctxs = NULL;
 }
 
-static struct rpcrdma_sendctx *rpcrdma_sendctx_create(struct rpcrdma_ia *ia)
+static struct rpcrdma_sendctx *rpcrdma_sendctx_create(struct rpcrdma_ep *ep)
 {
        struct rpcrdma_sendctx *sc;
 
-       sc = kzalloc(struct_size(sc, sc_sges, ia->ri_max_send_sges),
+       sc = kzalloc(struct_size(sc, sc_sges, ep->rep_attr.cap.max_send_sge),
                     GFP_KERNEL);
        if (!sc)
                return NULL;
@@ -821,20 +822,21 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
         * Sends are posted.
         */
        i = buf->rb_max_requests + RPCRDMA_MAX_BC_REQUESTS;
-       dprintk("RPC:       %s: allocating %lu send_ctxs\n", __func__, i);
        buf->rb_sc_ctxs = kcalloc(i, sizeof(sc), GFP_KERNEL);
        if (!buf->rb_sc_ctxs)
                return -ENOMEM;
 
        buf->rb_sc_last = i - 1;
        for (i = 0; i <= buf->rb_sc_last; i++) {
-               sc = rpcrdma_sendctx_create(&r_xprt->rx_ia);
+               sc = rpcrdma_sendctx_create(&r_xprt->rx_ep);
                if (!sc)
                        return -ENOMEM;
 
                buf->rb_sc_ctxs[i] = sc;
        }
 
+       buf->rb_sc_head = 0;
+       buf->rb_sc_tail = 0;
        return 0;
 }
 
@@ -1092,6 +1094,7 @@ static struct rpcrdma_rep *rpcrdma_rep_create(struct rpcrdma_xprt *r_xprt,
        rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
        rep->rr_recv_wr.num_sge = 1;
        rep->rr_temp = temp;
+       list_add(&rep->rr_all, &r_xprt->rx_buf.rb_all_reps);
        return rep;
 
 out_free:
@@ -1102,6 +1105,7 @@ static struct rpcrdma_rep *rpcrdma_rep_create(struct rpcrdma_xprt *r_xprt,
 
 static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep)
 {
+       list_del(&rep->rr_all);
        rpcrdma_regbuf_free(rep->rr_rdmabuf);
        kfree(rep);
 }
@@ -1120,10 +1124,16 @@ static struct rpcrdma_rep *rpcrdma_rep_get_locked(struct rpcrdma_buffer *buf)
 static void rpcrdma_rep_put(struct rpcrdma_buffer *buf,
                            struct rpcrdma_rep *rep)
 {
-       if (!rep->rr_temp)
-               llist_add(&rep->rr_node, &buf->rb_free_reps);
-       else
-               rpcrdma_rep_destroy(rep);
+       llist_add(&rep->rr_node, &buf->rb_free_reps);
+}
+
+static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct rpcrdma_rep *rep;
+
+       list_for_each_entry(rep, &buf->rb_all_reps, rr_all)
+               rpcrdma_regbuf_dma_unmap(rep->rr_rdmabuf);
 }
 
 static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf)
@@ -1154,6 +1164,7 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
 
        INIT_LIST_HEAD(&buf->rb_send_bufs);
        INIT_LIST_HEAD(&buf->rb_allreqs);
+       INIT_LIST_HEAD(&buf->rb_all_reps);
 
        rc = -ENOMEM;
        for (i = 0; i < buf->rb_max_requests; i++) {
@@ -1168,10 +1179,6 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
 
        init_llist_head(&buf->rb_free_reps);
 
-       rc = rpcrdma_sendctxs_create(r_xprt);
-       if (rc)
-               goto out;
-
        return 0;
 out:
        rpcrdma_buffer_destroy(buf);
@@ -1247,7 +1254,6 @@ static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt)
 void
 rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
 {
-       rpcrdma_sendctxs_destroy(buf);
        rpcrdma_reps_destroy(buf);
 
        while (!list_empty(&buf->rb_send_bufs)) {
@@ -1506,6 +1512,10 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp)
        wr = NULL;
        while (needed) {
                rep = rpcrdma_rep_get_locked(buf);
+               if (rep && rep->rr_temp) {
+                       rpcrdma_rep_destroy(rep);
+                       continue;
+               }
                if (!rep)
                        rep = rpcrdma_rep_create(r_xprt, temp);
                if (!rep)