From 15b3ea37334ca66abb9106168cdc761538847cde Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 26 Aug 2015 14:27:00 -0600 Subject: [PATCH] svcrdma: Add svc_rdma_get_context() API that is allowed to fail [ Proposed for v4.4 ] To support backward direction calls, I'm going to add an svc_rdma_get_context() call in the client RDMA transport. Called from ->buf_alloc(), we can't sleep waiting for memory. So add an API that can get a server op_ctxt but won't sleep. Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc_rdma.h | 2 ++ net/sunrpc/xprtrdma/svc_rdma_transport.c | 28 +++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index a91f760254d9..ae5828377522 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h @@ -223,6 +223,8 @@ extern void svc_rdma_send_error(struct svcxprt_rdma *, struct rpcrdma_msg *, extern int svc_rdma_post_recv(struct svcxprt_rdma *); extern int svc_rdma_create_listen(struct svc_serv *, int, struct sockaddr *); extern struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *); +extern struct svc_rdma_op_ctxt *svc_rdma_get_context_gfp(struct svcxprt_rdma *, + gfp_t); extern void svc_rdma_put_context(struct svc_rdma_op_ctxt *, int); extern void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt); extern struct svc_rdma_req_map *svc_rdma_get_req_map(void); diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index e35cf9c5fe81..bc8b46e49638 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -153,17 +153,35 @@ static void svc_rdma_bc_free(struct svc_xprt *xprt) } #endif /* CONFIG_SUNRPC_BACKCHANNEL */ -struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) +static void svc_rdma_init_context(struct svcxprt_rdma *xprt, + struct svc_rdma_op_ctxt *ctxt) { - struct svc_rdma_op_ctxt *ctxt; - - ctxt = kmem_cache_alloc(svc_rdma_ctxt_cachep, - GFP_KERNEL | __GFP_NOFAIL); ctxt->xprt = xprt; INIT_LIST_HEAD(&ctxt->dto_q); ctxt->count = 0; ctxt->frmr = NULL; atomic_inc(&xprt->sc_ctxt_used); +} + +struct svc_rdma_op_ctxt *svc_rdma_get_context_gfp(struct svcxprt_rdma *xprt, + gfp_t flags) +{ + struct svc_rdma_op_ctxt *ctxt; + + ctxt = kmem_cache_alloc(svc_rdma_ctxt_cachep, flags); + if (!ctxt) + return NULL; + svc_rdma_init_context(xprt, ctxt); + return ctxt; +} + +struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) +{ + struct svc_rdma_op_ctxt *ctxt; + + ctxt = kmem_cache_alloc(svc_rdma_ctxt_cachep, + GFP_KERNEL | __GFP_NOFAIL); + svc_rdma_init_context(xprt, ctxt); return ctxt; } -- 2.50.1