Add pre-fencing grace period when starting a new server

One of the first steps in starting a new server is to fence the
previous server if it's still running. This happens nearly immediately,
and it can take some time for the old server to shut down cleanly.
So we're often fencing when we should really just be patient.

Add a grace period, currently up to about 10s, watching for an old
server to write out its STOP record. After that, go ahead and fence.

Signed-off-by: Chris Kirby <ckirby@versity.com>
This commit is contained in:
Chris Kirby
2026-10-13 12:34:47 -05:00
parent 81879c693c
commit 73da218bc2
2 changed files with 19 additions and 3 deletions
+13 -2
View File
@@ -536,17 +536,21 @@ static int update_quorum_block(struct super_block *sb, int event, u64 term, bool
*
* Quorum will be sending heartbeats while we wait for fencing. That
* keeps us from being fenced while we allow userspace fencing to take a
* reasonably long time. We still want to timeout eventually.
* reasonably long time. We still want to time out eventually.
*/
#define SCOUTFS_OLD_LEADER_GRACE_PERIOD ((time64_t)10) /* arbitrary number of seconds */
int scoutfs_quorum_fence_leaders(struct super_block *sb, struct scoutfs_quorum_config *qconf,
u64 term)
{
#define NR_OLD 2
struct scoutfs_quorum_block_event old[SCOUTFS_QUORUM_MAX_SLOTS][NR_OLD] = {{{0,}}};
struct scoutfs_quorum_block_event old[SCOUTFS_QUORUM_MAX_SLOTS][NR_OLD];
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_quorum_block blk;
struct sockaddr_in sin;
const __le64 lefsid = cpu_to_le64(sbi->fsid);
time64_t start = ktime_get_seconds();
const u64 rid = sbi->rid;
bool fence_started = false;
u64 fenced = 0;
@@ -558,6 +562,9 @@ int scoutfs_quorum_fence_leaders(struct super_block *sb, struct scoutfs_quorum_c
BUILD_BUG_ON(SCOUTFS_QUORUM_BLOCKS < SCOUTFS_QUORUM_MAX_SLOTS);
restart:
memset(old, 0, sizeof(old));
for (i = 0; i < SCOUTFS_QUORUM_MAX_SLOTS; i++) {
if (!quorum_slot_present(qconf, i))
continue;
@@ -591,6 +598,10 @@ int scoutfs_quorum_fence_leaders(struct super_block *sb, struct scoutfs_quorum_c
le64_to_cpu(old[i][j].rid) == rid) /* us */
continue;
/* Give any previous leader(s) a grace period before fencing */
if (ktime_get_seconds() - start < SCOUTFS_OLD_LEADER_GRACE_PERIOD)
goto restart;
scoutfs_inc_counter(sb, quorum_fence_leader);
quorum_slot_sin(qconf, i, &sin);
fence_rid = old[i][j].rid;
+6 -1
View File
@@ -78,7 +78,12 @@ test_timeout()
# make sure the new leader delay was reasonable, allowing for some slack
low=$((to - 1000))
high=$((to + 5000))
# There's a race with the old server shutting down and writing its
# STOP record, which will trigger a delay (SCOUTFS_OLD_LEADER_GRACE_PERIOD)
# while the new server gives the old one a grace period. That duration needs
# to be included in the upper limit.
high=$((to + 15000))
# make sure the new leader delay was reasonable
test "$delay" -lt "$low" && t_fail "delay $delay < low $low (to $to)"