Commit 2d77058c authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker

xprtrdma: MR-related memory allocation should be allowed to fail

xprtrdma always drives a retry of MR allocation if it should fail.
It should be safe to not use GFP_KERNEL for this purpose rather
than sleeping in the memory allocator.

In theory, if these weaker allocations are attempted first, memory
exhaustion is likely to cause xprtrdma to fail fast and not then
invoke the RDMA core APIs, which still might use GFP_KERNEL.

Also note that rpc_task_gfp_mask() always sets __GFP_NORETRY and
__GFP_NOWARN when an RPC-related allocation is being done in a
worker thread. MR allocation is already always done in worker
threads.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 7ac18798
...@@ -126,14 +126,15 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr) ...@@ -126,14 +126,15 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr)
struct ib_mr *frmr; struct ib_mr *frmr;
int rc; int rc;
sg = kcalloc_node(depth, sizeof(*sg), XPRTRDMA_GFP_FLAGS,
ibdev_to_node(ep->re_id->device));
if (!sg)
return -ENOMEM;
frmr = ib_alloc_mr(ep->re_pd, ep->re_mrtype, depth); frmr = ib_alloc_mr(ep->re_pd, ep->re_mrtype, depth);
if (IS_ERR(frmr)) if (IS_ERR(frmr))
goto out_mr_err; goto out_mr_err;
sg = kmalloc_array(depth, sizeof(*sg), GFP_KERNEL);
if (!sg)
goto out_list_err;
mr->mr_xprt = r_xprt; mr->mr_xprt = r_xprt;
mr->mr_ibmr = frmr; mr->mr_ibmr = frmr;
mr->mr_device = NULL; mr->mr_device = NULL;
...@@ -146,13 +147,9 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr) ...@@ -146,13 +147,9 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr)
return 0; return 0;
out_mr_err: out_mr_err:
rc = PTR_ERR(frmr); kfree(sg);
trace_xprtrdma_frwr_alloc(mr, rc); trace_xprtrdma_frwr_alloc(mr, rc);
return rc; return PTR_ERR(frmr);
out_list_err:
ib_dereg_mr(frmr);
return -ENOMEM;
} }
/** /**
......
...@@ -739,13 +739,16 @@ rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt) ...@@ -739,13 +739,16 @@ rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt)
{ {
struct rpcrdma_buffer *buf = &r_xprt->rx_buf; struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
struct rpcrdma_ep *ep = r_xprt->rx_ep; struct rpcrdma_ep *ep = r_xprt->rx_ep;
struct ib_device *device = ep->re_id->device;
unsigned int count; unsigned int count;
/* Try to allocate enough to perform one full-sized I/O */
for (count = 0; count < ep->re_max_rdma_segs; count++) { for (count = 0; count < ep->re_max_rdma_segs; count++) {
struct rpcrdma_mr *mr; struct rpcrdma_mr *mr;
int rc; int rc;
mr = kzalloc(sizeof(*mr), GFP_KERNEL); mr = kzalloc_node(sizeof(*mr), XPRTRDMA_GFP_FLAGS,
ibdev_to_node(device));
if (!mr) if (!mr)
break; break;
......
...@@ -149,6 +149,12 @@ static inline void *rdmab_data(const struct rpcrdma_regbuf *rb) ...@@ -149,6 +149,12 @@ static inline void *rdmab_data(const struct rpcrdma_regbuf *rb)
return rb->rg_data; return rb->rg_data;
} }
/* Do not use emergency memory reserves, and fail quickly if memory
* cannot be allocated easily. These flags may be used wherever there
* is robust logic to handle a failure to allocate.
*/
#define XPRTRDMA_GFP_FLAGS (__GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN)
/* To ensure a transport can always make forward progress, /* To ensure a transport can always make forward progress,
* the number of RDMA segments allowed in header chunk lists * the number of RDMA segments allowed in header chunk lists
* is capped at 16. This prevents less-capable devices from * is capped at 16. This prevents less-capable devices from
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment