Check for fenced old leader in mounted test.

The old mounted check only considered begin/end quorum data, and
not whether the old leader that is now disconnected was fenced by
a new quorum leader.

Since this is the quaranteed case if the leader is disconnected
forcefully, this check must account for this case, so that quorum slots
can be modified if the node is permanently removed or replaced.

Signed-off-by: Auke Kok <auke.kok@versity.com>
This commit is contained in:
Auke Kok
2025-09-15 15:13:40 -04:00
parent e194714004
commit a87e92c1ad

View File

@@ -198,11 +198,13 @@ int write_block_sync(int fd, u32 magic, __le64 fsid, u64 seq, u64 blkno,
*/
int meta_super_in_use(int meta_fd, struct scoutfs_super_block *meta_super)
{
struct scoutfs_quorum_block *qblk = NULL;
struct scoutfs_quorum_block *qblk[SCOUTFS_QUORUM_BLOCKS] = {NULL,};
struct scoutfs_quorum_block_event *beg;
struct scoutfs_quorum_block_event *end;
struct scoutfs_quorum_block_event *fence;
bool beg_was_fenced;
int ret = 0;
int i;
int i, j;
if (meta_super->mounted_clients.ref.blkno != 0) {
fprintf(stderr, "meta superblock mounted clients btree is not empty.\n");
@@ -210,36 +212,61 @@ int meta_super_in_use(int meta_fd, struct scoutfs_super_block *meta_super)
goto out;
}
/* check for active quorum slots */
/* read all blocks */
for (i = 0; i < SCOUTFS_QUORUM_BLOCKS; i++) {
if (!quorum_slot_present(meta_super, i))
continue;
ret = read_block(meta_fd, SCOUTFS_QUORUM_BLKNO + i, SCOUTFS_BLOCK_SM_SHIFT,
(void **)&qblk);
(void **)&qblk[i]);
if (ret < 0) {
fprintf(stderr, "error reading quorum block for slot %u\n", i);
goto out;
}
}
beg = &qblk->events[SCOUTFS_QUORUM_EVENT_BEGIN];
end = &qblk->events[SCOUTFS_QUORUM_EVENT_END];
/* check for active quorum slots */
for (i = 0; i < SCOUTFS_QUORUM_BLOCKS; i++) {
if (!qblk[i])
continue;
if (le64_to_cpu(beg->write_nr) > le64_to_cpu(end->write_nr)) {
fprintf(stderr, "mount in quorum slot %u could still be running.\n"
" begin event: write_nr %llu timestamp %llu.%08u\n"
" end event: write_nr %llu timestamp %llu.%08u\n",
i, le64_to_cpu(beg->write_nr), le64_to_cpu(beg->ts.sec),
le32_to_cpu(beg->ts.nsec),
le64_to_cpu(end->write_nr), le64_to_cpu(end->ts.sec),
le32_to_cpu(end->ts.nsec));
ret = -EBUSY;
goto out;
beg = &qblk[i]->events[SCOUTFS_QUORUM_EVENT_BEGIN];
end = &qblk[i]->events[SCOUTFS_QUORUM_EVENT_END];
if (le64_to_cpu(beg->write_nr) <= le64_to_cpu(end->write_nr))
continue;
/* check if this term was fenced by others in a later term */
beg_was_fenced = false;
for (j = 0; j < SCOUTFS_QUORUM_BLOCKS; j++) {
if ((!qblk[j]) || (i == j))
continue;
fence = &qblk[j]->events[SCOUTFS_QUORUM_EVENT_FENCE];
if (le64_to_cpu(fence->term) > le64_to_cpu(beg->term)) {
beg_was_fenced = true;
break;
}
}
free(qblk);
qblk = NULL;
if (beg_was_fenced)
continue;
fprintf(stderr, "mount in quorum slot %u could still be running.\n"
" begin event: write_nr %llu timestamp %llu.%08u\n"
" end event: write_nr %llu timestamp %llu.%08u\n",
i, le64_to_cpu(beg->write_nr), le64_to_cpu(beg->ts.sec),
le32_to_cpu(beg->ts.nsec),
le64_to_cpu(end->write_nr), le64_to_cpu(end->ts.sec),
le32_to_cpu(end->ts.nsec));
ret = -EBUSY;
goto out;
}
out:
/* free any allocated blocks */
for (i = 0; i < SCOUTFS_QUORUM_BLOCKS; i++)
if (qblk[i] != NULL)
free(qblk[i]);
return ret;
}