Merge tag 'nfs-for-4.18-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[sfrench/cifs-2.6.git] / net / sunrpc / xprtrdma / transport.c
index caca977e375538d7780e04461369c5da42a499d6..143ce2579ba90cca47a87b5413ba35caf9d10792 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
  * Copyright (c) 2014-2017 Oracle.  All rights reserved.
  * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -334,9 +335,7 @@ xprt_setup_rdma(struct xprt_create *args)
                return ERR_PTR(-EBADF);
        }
 
-       xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt),
-                       xprt_rdma_slot_table_entries,
-                       xprt_rdma_slot_table_entries);
+       xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt), 0, 0);
        if (xprt == NULL) {
                dprintk("RPC:       %s: couldn't allocate rpcrdma_xprt\n",
                        __func__);
@@ -368,7 +367,7 @@ xprt_setup_rdma(struct xprt_create *args)
                xprt_set_bound(xprt);
        xprt_rdma_format_addresses(xprt, sap);
 
-       cdata.max_requests = xprt->max_reqs;
+       cdata.max_requests = xprt_rdma_slot_table_entries;
 
        cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */
        cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */
@@ -541,6 +540,47 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
        }
 }
 
+/**
+ * xprt_rdma_alloc_slot - allocate an rpc_rqst
+ * @xprt: controlling RPC transport
+ * @task: RPC task requesting a fresh rpc_rqst
+ *
+ * tk_status values:
+ *     %0 if task->tk_rqstp points to a fresh rpc_rqst
+ *     %-EAGAIN if no rpc_rqst is available; queued on backlog
+ */
+static void
+xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+       struct rpcrdma_req *req;
+
+       req = rpcrdma_buffer_get(&r_xprt->rx_buf);
+       if (!req)
+               goto out_sleep;
+       task->tk_rqstp = &req->rl_slot;
+       task->tk_status = 0;
+       return;
+
+out_sleep:
+       rpc_sleep_on(&xprt->backlog, task, NULL);
+       task->tk_status = -EAGAIN;
+}
+
+/**
+ * xprt_rdma_free_slot - release an rpc_rqst
+ * @xprt: controlling RPC transport
+ * @rqst: rpc_rqst to release
+ *
+ */
+static void
+xprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst)
+{
+       memset(rqst, 0, sizeof(*rqst));
+       rpcrdma_buffer_put(rpcr_to_rdmar(rqst));
+       rpc_wake_up_next(&xprt->backlog);
+}
+
 static bool
 rpcrdma_get_sendbuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
                    size_t size, gfp_t flags)
@@ -611,13 +651,9 @@ xprt_rdma_allocate(struct rpc_task *task)
 {
        struct rpc_rqst *rqst = task->tk_rqstp;
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);
-       struct rpcrdma_req *req;
+       struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
        gfp_t flags;
 
-       req = rpcrdma_buffer_get(&r_xprt->rx_buf);
-       if (req == NULL)
-               goto out_get;
-
        flags = RPCRDMA_DEF_GFP;
        if (RPC_IS_SWAPPER(task))
                flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
@@ -627,15 +663,12 @@ xprt_rdma_allocate(struct rpc_task *task)
        if (!rpcrdma_get_recvbuf(r_xprt, req, rqst->rq_rcvsize, flags))
                goto out_fail;
 
-       rpcrdma_set_xprtdata(rqst, req);
        rqst->rq_buffer = req->rl_sendbuf->rg_base;
        rqst->rq_rbuffer = req->rl_recvbuf->rg_base;
        trace_xprtrdma_allocate(task, req);
        return 0;
 
 out_fail:
-       rpcrdma_buffer_put(req);
-out_get:
        trace_xprtrdma_allocate(task, NULL);
        return -ENOMEM;
 }
@@ -656,7 +689,6 @@ xprt_rdma_free(struct rpc_task *task)
        if (test_bit(RPCRDMA_REQ_F_PENDING, &req->rl_flags))
                rpcrdma_release_rqst(r_xprt, req);
        trace_xprtrdma_rpc_done(task, req);
-       rpcrdma_buffer_put(req);
 }
 
 /**
@@ -694,9 +726,6 @@ xprt_rdma_send_request(struct rpc_task *task)
        if (rc < 0)
                goto failed_marshal;
 
-       if (req->rl_reply == NULL)              /* e.g. reconnection */
-               rpcrdma_recv_buffer_get(req);
-
        /* Must suppress retransmit to maintain credits */
        if (rqst->rq_connect_cookie == xprt->connect_cookie)
                goto drop_connection;
@@ -783,7 +812,8 @@ xprt_rdma_disable_swap(struct rpc_xprt *xprt)
 static const struct rpc_xprt_ops xprt_rdma_procs = {
        .reserve_xprt           = xprt_reserve_xprt_cong,
        .release_xprt           = xprt_release_xprt_cong, /* sunrpc/xprt.c */
-       .alloc_slot             = xprt_alloc_slot,
+       .alloc_slot             = xprt_rdma_alloc_slot,
+       .free_slot              = xprt_rdma_free_slot,
        .release_request        = xprt_release_rqst_cong,       /* ditto */
        .set_retrans_timeout    = xprt_set_retrans_timeout_def, /* ditto */
        .timer                  = xprt_rdma_timer,