From 48d849e2f4f8bc280f09a0ecf580f5a416cb20f2 Mon Sep 17 00:00:00 2001 From: Chris Kirby Date: Wed, 16 Jul 2025 14:09:07 -0500 Subject: [PATCH] Only start new quorum election after a receive failure It's possible for the quorum worker to be preempted for a long period, especially on debug kernels. Since we only check for how much time has passed, it's possible for a clean receive to inadvertently trigger an election. This can cause the quorum-heartbeat-timeout test to fail due to observed delays outside of the expected bounds. Instead, make sure we had a receive failure before comparing timestamps. Signed-off-by: Chris Kirby --- kmod/src/quorum.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kmod/src/quorum.c b/kmod/src/quorum.c index 7308b1dc..264ad9b1 100644 --- a/kmod/src/quorum.c +++ b/kmod/src/quorum.c @@ -726,6 +726,8 @@ static void scoutfs_quorum_worker(struct work_struct *work) struct quorum_status qst = {0,}; struct hb_recording hbr; bool record_hb; + bool recv_failed; + bool initializing = true; int ret; int err; @@ -758,6 +760,8 @@ static void scoutfs_quorum_worker(struct work_struct *work) update_show_status(qinf, &qst); + recv_failed = false; + ret = recv_msg(sb, &msg, qst.timeout); if (ret < 0) { if (ret != -ETIMEDOUT && ret != -EAGAIN) { @@ -765,6 +769,9 @@ static void scoutfs_quorum_worker(struct work_struct *work) scoutfs_inc_counter(sb, quorum_recv_error); goto out; } + + recv_failed = true; + msg.type = SCOUTFS_QUORUM_MSG_INVALID; ret = 0; } @@ -822,12 +829,13 @@ static void scoutfs_quorum_worker(struct work_struct *work) /* followers and candidates start new election on timeout */ if (qst.role != LEADER && + (initializing || recv_failed) && ktime_after(ktime_get(), qst.timeout)) { /* .. but only if their server has stopped */ if (!scoutfs_server_is_down(sb)) { qst.timeout = election_timeout(); scoutfs_inc_counter(sb, quorum_candidate_server_stopping); - continue; + goto again; } qst.role = CANDIDATE; @@ -964,6 +972,9 @@ static void scoutfs_quorum_worker(struct work_struct *work) } record_hb_delay(sb, qinf, &hbr, record_hb, qst.role); + +again: + initializing = false; } update_show_status(qinf, &qst);