mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 00:21:59 +00:00
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
@ -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…
Reference in New Issue
Block a user