lkml.org 
[lkml]   [2022]   [Apr]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 184/219] SUNRPC: Fix NFSDs request deferral on RDMA transports
    Date
    From: Chuck Lever <chuck.lever@oracle.com>

    commit 773f91b2cf3f52df0d7508fdbf60f37567cdaee4 upstream.

    Trond Myklebust reports an NFSD crash in svc_rdma_sendto(). Further
    investigation shows that the crash occurred while NFSD was handling
    a deferred request.

    This patch addresses two inter-related issues that prevent request
    deferral from working correctly for RPC/RDMA requests:

    1. Prevent the crash by ensuring that the original
    svc_rqst::rq_xprt_ctxt value is available when the request is
    revisited. Otherwise svc_rdma_sendto() does not have a Receive
    context available with which to construct its reply.

    2. Possibly since before commit 71641d99ce03 ("svcrdma: Properly
    compute .len and .buflen for received RPC Calls"),
    svc_rdma_recvfrom() did not include the transport header in the
    returned xdr_buf. There should have been no need for svc_defer()
    and friends to save and restore that header, as of that commit.
    This issue is addressed in a backport-friendly way by simply
    having svc_rdma_recvfrom() set rq_xprt_hlen to zero
    unconditionally, just as svc_tcp_recvfrom() does. This enables
    svc_deferred_recv() to correctly reconstruct an RPC message
    received via RPC/RDMA.

    Reported-by: Trond Myklebust <trondmy@hammerspace.com>
    Link: https://lore.kernel.org/linux-nfs/82662b7190f26fb304eb0ab1bb04279072439d4e.camel@hammerspace.com/
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/linux/sunrpc/svc.h | 1 +
    net/sunrpc/svc_xprt.c | 3 +++
    net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 2 +-
    3 files changed, 5 insertions(+), 1 deletion(-)

    --- a/include/linux/sunrpc/svc.h
    +++ b/include/linux/sunrpc/svc.h
    @@ -412,6 +412,7 @@ struct svc_deferred_req {
    size_t addrlen;
    struct sockaddr_storage daddr; /* where reply must come from */
    size_t daddrlen;
    + void *xprt_ctxt;
    struct cache_deferred_req handle;
    size_t xprt_hlen;
    int argslen;
    --- a/net/sunrpc/svc_xprt.c
    +++ b/net/sunrpc/svc_xprt.c
    @@ -1213,6 +1213,8 @@ static struct cache_deferred_req *svc_de
    dr->daddr = rqstp->rq_daddr;
    dr->argslen = rqstp->rq_arg.len >> 2;
    dr->xprt_hlen = rqstp->rq_xprt_hlen;
    + dr->xprt_ctxt = rqstp->rq_xprt_ctxt;
    + rqstp->rq_xprt_ctxt = NULL;

    /* back up head to the start of the buffer and copy */
    skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
    @@ -1251,6 +1253,7 @@ static noinline int svc_deferred_recv(st
    rqstp->rq_xprt_hlen = dr->xprt_hlen;
    rqstp->rq_daddr = dr->daddr;
    rqstp->rq_respages = rqstp->rq_pages;
    + rqstp->rq_xprt_ctxt = dr->xprt_ctxt;
    svc_xprt_received(rqstp->rq_xprt);
    return (dr->argslen<<2) - dr->xprt_hlen;
    }
    --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
    +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
    @@ -831,7 +831,7 @@ int svc_rdma_recvfrom(struct svc_rqst *r
    goto out_err;
    if (ret == 0)
    goto out_drop;
    - rqstp->rq_xprt_hlen = ret;
    + rqstp->rq_xprt_hlen = 0;

    if (svc_rdma_is_reverse_direction_reply(xprt, ctxt))
    goto out_backchannel;

    \
     
     \ /
      Last update: 2022-04-18 14:38    [W:4.042 / U:0.748 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site