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_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
|
||||||
|
|
Loading…
Reference in New Issue