xprtrdma: Improve locking around rpcrdma_rep destruction
Currently rpcrdma_reps_destroy() assumes that, at transport tear-down, the content of the rb_free_reps list is the same as the content of the rb_all_reps list. Although that is usually true, using the rb_all_reps list should be more reliable because of the way it's managed. And, rpcrdma_reps_unmap() uses rb_all_reps; these two functions should both traverse the "all" list. Ensure that all rpcrdma_reps are always destroyed whether they are on the rep free list or not. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
5030c9a938
commit
eaf86e8cc8
1 changed files with 24 additions and 7 deletions
|
|
@ -1007,16 +1007,23 @@ out:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* No locking needed here. This function is invoked only by the
|
||||
* Receive completion handler, or during transport shutdown.
|
||||
*/
|
||||
static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep)
|
||||
static void rpcrdma_rep_free(struct rpcrdma_rep *rep)
|
||||
{
|
||||
list_del(&rep->rr_all);
|
||||
rpcrdma_regbuf_free(rep->rr_rdmabuf);
|
||||
kfree(rep);
|
||||
}
|
||||
|
||||
static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep)
|
||||
{
|
||||
struct rpcrdma_buffer *buf = &rep->rr_rxprt->rx_buf;
|
||||
|
||||
spin_lock(&buf->rb_lock);
|
||||
list_del(&rep->rr_all);
|
||||
spin_unlock(&buf->rb_lock);
|
||||
|
||||
rpcrdma_rep_free(rep);
|
||||
}
|
||||
|
||||
static struct rpcrdma_rep *rpcrdma_rep_get_locked(struct rpcrdma_buffer *buf)
|
||||
{
|
||||
struct llist_node *node;
|
||||
|
|
@ -1049,8 +1056,18 @@ static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf)
|
|||
{
|
||||
struct rpcrdma_rep *rep;
|
||||
|
||||
while ((rep = rpcrdma_rep_get_locked(buf)) != NULL)
|
||||
rpcrdma_rep_destroy(rep);
|
||||
spin_lock(&buf->rb_lock);
|
||||
while ((rep = list_first_entry_or_null(&buf->rb_all_reps,
|
||||
struct rpcrdma_rep,
|
||||
rr_all)) != NULL) {
|
||||
list_del(&rep->rr_all);
|
||||
spin_unlock(&buf->rb_lock);
|
||||
|
||||
rpcrdma_rep_free(rep);
|
||||
|
||||
spin_lock(&buf->rb_lock);
|
||||
}
|
||||
spin_unlock(&buf->rb_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue