Commit f5fe8d51 authored by Alexander Aring's avatar Alexander Aring Committed by David Teigland

fs: dlm: fix race in mhandle deletion

This patch fixes a race between mhandle deletion in case of receiving an
acknowledge and flush of all pending mhandle in cases of an timeout or
resetting node states.

Fixes: 489d8e55 ("fs: dlm: add reliable connection if reconnect")
Reported-by: default avatarGuillaume Nault <gnault@redhat.com>
Signed-off-by: default avatarAlexander Aring <aahringo@redhat.com>
Signed-off-by: default avatarDavid Teigland <teigland@redhat.com>
parent d10a0b88
...@@ -287,6 +287,14 @@ static void dlm_mhandle_release(struct rcu_head *rcu) ...@@ -287,6 +287,14 @@ static void dlm_mhandle_release(struct rcu_head *rcu)
kfree(mh); kfree(mh);
} }
static void dlm_mhandle_delete(struct midcomms_node *node,
struct dlm_mhandle *mh)
{
list_del_rcu(&mh->list);
atomic_dec(&node->send_queue_cnt);
call_rcu(&mh->rcu, dlm_mhandle_release);
}
static void dlm_send_queue_flush(struct midcomms_node *node) static void dlm_send_queue_flush(struct midcomms_node *node)
{ {
struct dlm_mhandle *mh; struct dlm_mhandle *mh;
...@@ -294,15 +302,11 @@ static void dlm_send_queue_flush(struct midcomms_node *node) ...@@ -294,15 +302,11 @@ static void dlm_send_queue_flush(struct midcomms_node *node)
pr_debug("flush midcomms send queue of node %d\n", node->nodeid); pr_debug("flush midcomms send queue of node %d\n", node->nodeid);
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(mh, &node->send_queue, list) {
spin_lock(&node->send_queue_lock); spin_lock(&node->send_queue_lock);
list_del_rcu(&mh->list); list_for_each_entry_rcu(mh, &node->send_queue, list) {
spin_unlock(&node->send_queue_lock); dlm_mhandle_delete(node, mh);
atomic_dec(&node->send_queue_cnt);
call_rcu(&mh->rcu, dlm_mhandle_release);
} }
spin_unlock(&node->send_queue_lock);
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -424,21 +428,24 @@ static void dlm_receive_ack(struct midcomms_node *node, uint32_t seq) ...@@ -424,21 +428,24 @@ static void dlm_receive_ack(struct midcomms_node *node, uint32_t seq)
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(mh, &node->send_queue, list) { list_for_each_entry_rcu(mh, &node->send_queue, list) {
if (before(mh->seq, seq)) { if (before(mh->seq, seq)) {
spin_lock(&node->send_queue_lock);
list_del_rcu(&mh->list);
spin_unlock(&node->send_queue_lock);
atomic_dec(&node->send_queue_cnt);
if (mh->ack_rcv) if (mh->ack_rcv)
mh->ack_rcv(node); mh->ack_rcv(node);
} else {
/* send queue should be ordered */
break;
}
}
call_rcu(&mh->rcu, dlm_mhandle_release); spin_lock(&node->send_queue_lock);
list_for_each_entry_rcu(mh, &node->send_queue, list) {
if (before(mh->seq, seq)) {
dlm_mhandle_delete(node, mh);
} else { } else {
/* send queue should be ordered */ /* send queue should be ordered */
break; break;
} }
} }
spin_unlock(&node->send_queue_lock);
rcu_read_unlock(); rcu_read_unlock();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment