fs: dlm: move sending fin message into state change handling
authorAlexander Aring <aahringo@redhat.com>
Thu, 12 Jan 2023 22:10:36 +0000 (17:10 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2023 08:39:58 +0000 (09:39 +0100)
commit a58496361802070996f9bd76e941d109c4a85ebd upstream.

This patch moves the send fin handling, which should appear in a specific
state change, into the state change handling while the per node
state_lock is held. I experienced issues with other messages because
we changed the state and a fin message was sent out in a different state.

Cc: stable@vger.kernel.org
Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect")
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/dlm/midcomms.c

index a4825539bb069938c52281966a4c5022a403ea99..e812e98098ecfc07156561843c8581d395847428 100644 (file)
@@ -394,7 +394,7 @@ static int dlm_send_fin(struct midcomms_node *node,
        struct dlm_mhandle *mh;
        char *ppc;
 
-       mh = dlm_midcomms_get_mhandle(node->nodeid, mb_len, GFP_NOFS, &ppc);
+       mh = dlm_midcomms_get_mhandle(node->nodeid, mb_len, GFP_ATOMIC, &ppc);
        if (!mh)
                return -ENOMEM;
 
@@ -498,8 +498,8 @@ static void dlm_midcomms_receive_buffer(union dlm_packet *p,
                                        node->state = DLM_LAST_ACK;
                                        pr_debug("switch node %d to state %s case 1\n",
                                                 node->nodeid, dlm_state_str(node->state));
-                                       spin_unlock(&node->state_lock);
-                                       goto send_fin;
+                                       set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags);
+                                       dlm_send_fin(node, dlm_pas_fin_ack_rcv);
                                }
                                break;
                        case DLM_FIN_WAIT1:
@@ -542,12 +542,6 @@ static void dlm_midcomms_receive_buffer(union dlm_packet *p,
                log_print_ratelimited("ignore dlm msg because seq mismatch, seq: %u, expected: %u, nodeid: %d",
                                      seq, node->seq_next, node->nodeid);
        }
-
-       return;
-
-send_fin:
-       set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags);
-       dlm_send_fin(node, dlm_pas_fin_ack_rcv);
 }
 
 static struct midcomms_node *
@@ -1268,11 +1262,11 @@ void dlm_midcomms_remove_member(int nodeid)
                case DLM_CLOSE_WAIT:
                        /* passive shutdown DLM_LAST_ACK case 2 */
                        node->state = DLM_LAST_ACK;
-                       spin_unlock(&node->state_lock);
-
                        pr_debug("switch node %d to state %s case 2\n",
                                 node->nodeid, dlm_state_str(node->state));
-                       goto send_fin;
+                       set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags);
+                       dlm_send_fin(node, dlm_pas_fin_ack_rcv);
+                       break;
                case DLM_LAST_ACK:
                        /* probably receive fin caught it, do nothing */
                        break;
@@ -1288,12 +1282,6 @@ void dlm_midcomms_remove_member(int nodeid)
        spin_unlock(&node->state_lock);
 
        srcu_read_unlock(&nodes_srcu, idx);
-       return;
-
-send_fin:
-       set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags);
-       dlm_send_fin(node, dlm_pas_fin_ack_rcv);
-       srcu_read_unlock(&nodes_srcu, idx);
 }
 
 static void midcomms_node_release(struct rcu_head *rcu)
@@ -1324,6 +1312,7 @@ static void midcomms_shutdown(struct midcomms_node *node)
                node->state = DLM_FIN_WAIT1;
                pr_debug("switch node %d to state %s case 2\n",
                         node->nodeid, dlm_state_str(node->state));
+               dlm_send_fin(node, dlm_act_fin_ack_rcv);
                break;
        case DLM_CLOSED:
                /* we have what we want */
@@ -1337,12 +1326,8 @@ static void midcomms_shutdown(struct midcomms_node *node)
        }
        spin_unlock(&node->state_lock);
 
-       if (node->state == DLM_FIN_WAIT1) {
-               dlm_send_fin(node, dlm_act_fin_ack_rcv);
-
-               if (DLM_DEBUG_FENCE_TERMINATION)
-                       msleep(5000);
-       }
+       if (DLM_DEBUG_FENCE_TERMINATION)
+               msleep(5000);
 
        /* wait for other side dlm + fin */
        ret = wait_event_timeout(node->shutdown_wait,