svcrdma: Add back svc_rdma_recv_ctxt::rc_pages
authorChuck Lever <chuck.lever@oracle.com>
Mon, 18 Dec 2023 22:31:48 +0000 (17:31 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Sun, 7 Jan 2024 22:54:32 +0000 (17:54 -0500)
Having an nfsd thread waiting for an RDMA Read completion is
problematic if the Read responder (the client) stops responding. We
need to go back to handling RDMA Reads by allowing the nfsd thread
to return to the svc scheduler, then waking a second thread finish
the RPC message once the Read completion fires.

To start with, restore the rc_pages field so that RDMA Read pages
can be managed across calls to svc_rdma_recvfrom().

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

index 46f2ce9f810b6cd9e1ef084af73435c2914389d6..0f2d7f68ef5d8e3f2f80afa61644518b6b451173 100644 (file)
@@ -183,7 +183,6 @@ struct svc_rdma_recv_ctxt {
        void                    *rc_recv_buf;
        struct xdr_stream       rc_stream;
        u32                     rc_byte_len;
-       unsigned int            rc_page_count;
        u32                     rc_inv_rkey;
        __be32                  rc_msgtype;
 
@@ -199,6 +198,9 @@ struct svc_rdma_recv_ctxt {
        struct svc_rdma_chunk   *rc_cur_result_payload;
        struct svc_rdma_pcl     rc_write_pcl;
        struct svc_rdma_pcl     rc_reply_pcl;
+
+       unsigned int            rc_page_count;
+       struct page             *rc_pages[RPCSVC_MAXPAGES];
 };
 
 struct svc_rdma_send_ctxt {
index 38f01652dc6d878d7364324aa5d2a3fd32c753a2..e363cb1bdbc4121327f2fba31c46d396851344d3 100644 (file)
@@ -214,6 +214,11 @@ struct svc_rdma_recv_ctxt *svc_rdma_recv_ctxt_get(struct svcxprt_rdma *rdma)
 void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
                            struct svc_rdma_recv_ctxt *ctxt)
 {
+       /* @rc_page_count is normally zero here, but error flows
+        * can leave pages in @rc_pages.
+        */
+       release_pages(ctxt->rc_pages, ctxt->rc_page_count);
+
        pcl_free(&ctxt->rc_call_pcl);
        pcl_free(&ctxt->rc_read_pcl);
        pcl_free(&ctxt->rc_write_pcl);
index ff54bb268b7d24ee777d143242a11e6cd630427c..28a34718dee5334e889c6d500284fcfd1aa7f693 100644 (file)
@@ -1131,7 +1131,9 @@ int svc_rdma_process_read_list(struct svcxprt_rdma *rdma,
        rqstp->rq_respages = &rqstp->rq_pages[head->rc_page_count];
        rqstp->rq_next_page = rqstp->rq_respages + 1;
 
-       /* Ensure svc_rdma_recv_ctxt_put() does not try to release pages */
+       /* Ensure svc_rdma_recv_ctxt_put() does not release pages
+        * left in @rc_pages while I/O proceeds.
+        */
        head->rc_page_count = 0;
 
 out_err: