]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
svcrdma: Factor out WR chain linking into helper
authorChuck Lever <chuck.lever@oracle.com>
Fri, 27 Feb 2026 14:03:32 +0000 (09:03 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 30 Mar 2026 01:25:09 +0000 (21:25 -0400)
svc_rdma_prepare_write_chunk() and svc_rdma_prepare_reply_chunk()
contain identical code for linking RDMA R/W work requests onto a
Send context's WR chain. This duplication increases maintenance
burden and risks divergent bug fixes.

Introduce svc_rdma_cc_link_wrs() to consolidate the WR chain
linking logic. The helper walks the chunk context's rwctxts list,
chains each WR via rdma_rw_ctx_wrs(), and updates the Send
context's chain head and SQE count. Completion signaling is
requested only for the tail WR (posted first).

No functional change.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
net/sunrpc/xprtrdma/svc_rdma_rw.c

index ebc90c12c835148205dcc5f0521b6279c5e462f0..9e17700fae2a6e712eb2e260f4dd8f22191250f5 100644 (file)
@@ -619,15 +619,32 @@ static int svc_rdma_xb_write(const struct xdr_buf *xdr, void *data)
        return xdr->len;
 }
 
-/*
- * svc_rdma_prepare_write_chunk - Link Write WRs for @chunk onto @sctxt's chain
- *
- * Write WRs are prepended to the Send WR chain so that a single
- * ib_post_send() posts both RDMA Writes and the final Send. Only
- * the first WR in each chunk gets a CQE for error detection;
- * subsequent WRs complete without individual completion events.
- * The Send WR's signaled completion indicates all chained
- * operations have finished.
+/* Link chunk WRs onto @sctxt's WR chain. Completion is requested
+ * for the tail WR, which is posted first.
+ */
+static void svc_rdma_cc_link_wrs(struct svcxprt_rdma *rdma,
+                                struct svc_rdma_send_ctxt *sctxt,
+                                struct svc_rdma_chunk_ctxt *cc)
+{
+       struct ib_send_wr *first_wr;
+       struct list_head *pos;
+       struct ib_cqe *cqe;
+
+       first_wr = sctxt->sc_wr_chain;
+       cqe = &cc->cc_cqe;
+       list_for_each(pos, &cc->cc_rwctxts) {
+               struct svc_rdma_rw_ctxt *rwc;
+
+               rwc = list_entry(pos, struct svc_rdma_rw_ctxt, rw_list);
+               first_wr = rdma_rw_ctx_wrs(&rwc->rw_ctx, rdma->sc_qp,
+                                          rdma->sc_port_num, cqe, first_wr);
+               cqe = NULL;
+       }
+       sctxt->sc_wr_chain = first_wr;
+       sctxt->sc_sqecount += cc->cc_sqecount;
+}
+
+/* Link Write WRs for @chunk onto @sctxt's WR chain.
  */
 static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
                                        struct svc_rdma_send_ctxt *sctxt,
@@ -636,10 +653,7 @@ static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
 {
        struct svc_rdma_write_info *info;
        struct svc_rdma_chunk_ctxt *cc;
-       struct ib_send_wr *first_wr;
        struct xdr_buf payload;
-       struct list_head *pos;
-       struct ib_cqe *cqe;
        int ret;
 
        if (xdr_buf_subsegment(xdr, &payload, chunk->ch_position,
@@ -659,18 +673,7 @@ static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
        if (unlikely(sctxt->sc_sqecount + cc->cc_sqecount > rdma->sc_sq_depth))
                goto out_err;
 
-       first_wr = sctxt->sc_wr_chain;
-       cqe = &cc->cc_cqe;
-       list_for_each(pos, &cc->cc_rwctxts) {
-               struct svc_rdma_rw_ctxt *rwc;
-
-               rwc = list_entry(pos, struct svc_rdma_rw_ctxt, rw_list);
-               first_wr = rdma_rw_ctx_wrs(&rwc->rw_ctx, rdma->sc_qp,
-                                          rdma->sc_port_num, cqe, first_wr);
-               cqe = NULL;
-       }
-       sctxt->sc_wr_chain = first_wr;
-       sctxt->sc_sqecount += cc->cc_sqecount;
+       svc_rdma_cc_link_wrs(rdma, sctxt, cc);
        list_add(&info->wi_list, &sctxt->sc_write_info_list);
 
        trace_svcrdma_post_write_chunk(&cc->cc_cid, cc->cc_sqecount);
@@ -732,9 +735,6 @@ int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma,
 {
        struct svc_rdma_write_info *info = &sctxt->sc_reply_info;
        struct svc_rdma_chunk_ctxt *cc = &info->wi_cc;
-       struct ib_send_wr *first_wr;
-       struct list_head *pos;
-       struct ib_cqe *cqe;
        int ret;
 
        info->wi_rdma = rdma;
@@ -748,18 +748,7 @@ int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma,
        if (ret < 0)
                return ret;
 
-       first_wr = sctxt->sc_wr_chain;
-       cqe = &cc->cc_cqe;
-       list_for_each(pos, &cc->cc_rwctxts) {
-               struct svc_rdma_rw_ctxt *rwc;
-
-               rwc = list_entry(pos, struct svc_rdma_rw_ctxt, rw_list);
-               first_wr = rdma_rw_ctx_wrs(&rwc->rw_ctx, rdma->sc_qp,
-                                          rdma->sc_port_num, cqe, first_wr);
-               cqe = NULL;
-       }
-       sctxt->sc_wr_chain = first_wr;
-       sctxt->sc_sqecount += cc->cc_sqecount;
+       svc_rdma_cc_link_wrs(rdma, sctxt, cc);
 
        trace_svcrdma_post_reply_chunk(&cc->cc_cid, cc->cc_sqecount);
        return xdr->len;