xprtrdma: Fix MR list handling

Close some holes introduced by commit 6dc6ec9e04 ("xprtrdma: Cache
free MRs in each rpcrdma_req") that could result in list corruption.

In addition, the result that is tabulated in @count is no longer
used, so @count is removed.

Fixes: 6dc6ec9e04 ("xprtrdma: Cache free MRs in each rpcrdma_req")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
Chuck Lever 2019-10-09 13:07:43 -04:00 committed by Anna Schumaker
parent 2ae50ad68c
commit c3700780a0

View file

@ -79,7 +79,6 @@ static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt);
static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf); static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf);
static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt); static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf); static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);
static void rpcrdma_mr_free(struct rpcrdma_mr *mr);
static struct rpcrdma_regbuf * static struct rpcrdma_regbuf *
rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction, rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction,
gfp_t flags); gfp_t flags);
@ -966,7 +965,7 @@ rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt)
mr->mr_xprt = r_xprt; mr->mr_xprt = r_xprt;
spin_lock(&buf->rb_lock); spin_lock(&buf->rb_lock);
list_add(&mr->mr_list, &buf->rb_mrs); rpcrdma_mr_push(mr, &buf->rb_mrs);
list_add(&mr->mr_all, &buf->rb_all_mrs); list_add(&mr->mr_all, &buf->rb_all_mrs);
spin_unlock(&buf->rb_lock); spin_unlock(&buf->rb_lock);
} }
@ -1183,10 +1182,19 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
*/ */
void rpcrdma_req_destroy(struct rpcrdma_req *req) void rpcrdma_req_destroy(struct rpcrdma_req *req)
{ {
struct rpcrdma_mr *mr;
list_del(&req->rl_all); list_del(&req->rl_all);
while (!list_empty(&req->rl_free_mrs)) while ((mr = rpcrdma_mr_pop(&req->rl_free_mrs))) {
rpcrdma_mr_free(rpcrdma_mr_pop(&req->rl_free_mrs)); struct rpcrdma_buffer *buf = &mr->mr_xprt->rx_buf;
spin_lock(&buf->rb_lock);
list_del(&mr->mr_all);
spin_unlock(&buf->rb_lock);
frwr_release_mr(mr);
}
rpcrdma_regbuf_free(req->rl_recvbuf); rpcrdma_regbuf_free(req->rl_recvbuf);
rpcrdma_regbuf_free(req->rl_sendbuf); rpcrdma_regbuf_free(req->rl_sendbuf);
@ -1194,24 +1202,28 @@ void rpcrdma_req_destroy(struct rpcrdma_req *req)
kfree(req); kfree(req);
} }
static void /**
rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf) * rpcrdma_mrs_destroy - Release all of a transport's MRs
* @buf: controlling buffer instance
*
* Relies on caller holding the transport send lock to protect
* removing mr->mr_list from req->rl_free_mrs safely.
*/
static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
{ {
struct rpcrdma_xprt *r_xprt = container_of(buf, struct rpcrdma_xprt, struct rpcrdma_xprt *r_xprt = container_of(buf, struct rpcrdma_xprt,
rx_buf); rx_buf);
struct rpcrdma_mr *mr; struct rpcrdma_mr *mr;
unsigned int count;
count = 0;
spin_lock(&buf->rb_lock); spin_lock(&buf->rb_lock);
while ((mr = list_first_entry_or_null(&buf->rb_all_mrs, while ((mr = list_first_entry_or_null(&buf->rb_all_mrs,
struct rpcrdma_mr, struct rpcrdma_mr,
mr_all)) != NULL) { mr_all)) != NULL) {
list_del(&mr->mr_list);
list_del(&mr->mr_all); list_del(&mr->mr_all);
spin_unlock(&buf->rb_lock); spin_unlock(&buf->rb_lock);
frwr_release_mr(mr); frwr_release_mr(mr);
count++;
spin_lock(&buf->rb_lock); spin_lock(&buf->rb_lock);
} }
spin_unlock(&buf->rb_lock); spin_unlock(&buf->rb_lock);
@ -1284,17 +1296,6 @@ void rpcrdma_mr_put(struct rpcrdma_mr *mr)
rpcrdma_mr_push(mr, &mr->mr_req->rl_free_mrs); rpcrdma_mr_push(mr, &mr->mr_req->rl_free_mrs);
} }
static void rpcrdma_mr_free(struct rpcrdma_mr *mr)
{
struct rpcrdma_xprt *r_xprt = mr->mr_xprt;
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
mr->mr_req = NULL;
spin_lock(&buf->rb_lock);
rpcrdma_mr_push(mr, &buf->rb_mrs);
spin_unlock(&buf->rb_lock);
}
/** /**
* rpcrdma_buffer_get - Get a request buffer * rpcrdma_buffer_get - Get a request buffer
* @buffers: Buffer pool from which to obtain a buffer * @buffers: Buffer pool from which to obtain a buffer