diff mbox series

NFSv4.1 backchannel xprt problems.

Message ID 87tv8iqz3b.fsf@notabene.neil.brown.name (mailing list archive)
State New, archived
Headers show
Series NFSv4.1 backchannel xprt problems. | expand

Commit Message

NeilBrown Oct. 9, 2019, 5:15 a.m. UTC
Hi,
 I have a customer with a 4.12-based kernel who is experiencing memory
 exhaustion.

 There are over 100,000 rpc_rqst structures queue on sv_cb_list for
 handing by the NFSv4 callback, which is idle.

 The rpc_rqst.rq_xprt pointer points to freed memory.

 I notice that that server code calls svc_xprt_get() on the xprt
 before storing it in rq_xprt, but the client/backchannel code doesn't.

 I'm wondering if the following might be useful.

 I plan to explore the code a bit more tomorrow and if this  still seems
 likely I get the customer to test this change, but I thought I would
 ask here as well incase someone more knowledgeable can give me any
 pointers.

Thanks,
NeilBrown

Comments

J. Bruce Fields Oct. 11, 2019, 4:56 p.m. UTC | #1
On Wed, Oct 09, 2019 at 04:15:04PM +1100, NeilBrown wrote:
>  I have a customer with a 4.12-based kernel who is experiencing memory
>  exhaustion.
> 
>  There are over 100,000 rpc_rqst structures queue on sv_cb_list for
>  handing by the NFSv4 callback, which is idle.
> 
>  The rpc_rqst.rq_xprt pointer points to freed memory.
> 
>  I notice that that server code calls svc_xprt_get() on the xprt
>  before storing it in rq_xprt, but the client/backchannel code doesn't.
> 
>  I'm wondering if the following might be useful.
> 
>  I plan to explore the code a bit more tomorrow and if this  still seems
>  likely I get the customer to test this change, but I thought I would
>  ask here as well incase someone more knowledgeable can give me any
>  pointers.

Looks sensible.  But if I ever understood how this works, I've got no
memory of it now....  Good luck.

> 
> Thanks,
> NeilBrown
> 
> diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
> index 339e8c077c2d..c95ca39688b6 100644
> --- a/net/sunrpc/backchannel_rqst.c
> +++ b/net/sunrpc/backchannel_rqst.c
> @@ -61,6 +61,7 @@ static void xprt_free_allocation(struct rpc_rqst *req)
>  	free_page((unsigned long)xbufp->head[0].iov_base);
>  	xbufp = &req->rq_snd_buf;
>  	free_page((unsigned long)xbufp->head[0].iov_base);
> +	xprt_put(req->rq_xprt);
>  	kfree(req);
>  }
>  
> @@ -85,7 +86,7 @@ struct rpc_rqst *xprt_alloc_bc_req(struct rpc_xprt *xprt, gfp_t gfp_flags)
>  	if (req == NULL)
>  		return NULL;
>  
> -	req->rq_xprt = xprt;
> +	req->rq_xprt = xprt_get(xprt);
>  	INIT_LIST_HEAD(&req->rq_bc_list);
>  
>  	/* Preallocate one XDR receive buffer */
diff mbox series

Patch

diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 339e8c077c2d..c95ca39688b6 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -61,6 +61,7 @@  static void xprt_free_allocation(struct rpc_rqst *req)
 	free_page((unsigned long)xbufp->head[0].iov_base);
 	xbufp = &req->rq_snd_buf;
 	free_page((unsigned long)xbufp->head[0].iov_base);
+	xprt_put(req->rq_xprt);
 	kfree(req);
 }
 
@@ -85,7 +86,7 @@  struct rpc_rqst *xprt_alloc_bc_req(struct rpc_xprt *xprt, gfp_t gfp_flags)
 	if (req == NULL)
 		return NULL;
 
-	req->rq_xprt = xprt;
+	req->rq_xprt = xprt_get(xprt);
 	INIT_LIST_HEAD(&req->rq_bc_list);
 
 	/* Preallocate one XDR receive buffer */