xprtrdma: Fix MR list handling
Close some holes introduced by commit6dc6ec9e04
("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:
parent
2ae50ad68c
commit
c3700780a0
|
@ -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_mrs_create(struct rpcrdma_xprt *r_xprt);
|
||||
static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);
|
||||
static void rpcrdma_mr_free(struct rpcrdma_mr *mr);
|
||||
static struct rpcrdma_regbuf *
|
||||
rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction,
|
||||
gfp_t flags);
|
||||
|
@ -966,7 +965,7 @@ rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt)
|
|||
mr->mr_xprt = r_xprt;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
struct rpcrdma_mr *mr;
|
||||
|
||||
list_del(&req->rl_all);
|
||||
|
||||
while (!list_empty(&req->rl_free_mrs))
|
||||
rpcrdma_mr_free(rpcrdma_mr_pop(&req->rl_free_mrs));
|
||||
while ((mr = 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_sendbuf);
|
||||
|
@ -1194,24 +1202,28 @@ void rpcrdma_req_destroy(struct rpcrdma_req *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,
|
||||
rx_buf);
|
||||
struct rpcrdma_mr *mr;
|
||||
unsigned int count;
|
||||
|
||||
count = 0;
|
||||
spin_lock(&buf->rb_lock);
|
||||
while ((mr = list_first_entry_or_null(&buf->rb_all_mrs,
|
||||
struct rpcrdma_mr,
|
||||
mr_all)) != NULL) {
|
||||
list_del(&mr->mr_list);
|
||||
list_del(&mr->mr_all);
|
||||
spin_unlock(&buf->rb_lock);
|
||||
|
||||
frwr_release_mr(mr);
|
||||
count++;
|
||||
spin_lock(&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);
|
||||
}
|
||||
|
||||
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
|
||||
* @buffers: Buffer pool from which to obtain a buffer
|
||||
|
|
Loading…
Reference in New Issue