Skip to content

fix: correct walfile_start_lsn mask that dropped the LSN high byte - #664

Open
jaideeppyne wants to merge 1 commit into
Aiven-Open:mainfrom
jaideeppyne:fix/walfile-start-lsn-high-logid
Open

jaideeppyne wants to merge 1 commit into
Aiven-Open:mainfrom
jaideeppyne:fix/walfile-start-lsn-high-logid

Conversation

@jaideeppyne

Copy link
Copy Markdown

What

LSN.walfile_start_lsn should return the start LSN of the WAL segment containing the LSN — self._seg * WAL_SEG_SIZE. It instead computed self.lsn & 0xFFFFFFFF000000.

Bug

That mask is one hex-digit-pair too short. Besides clearing the low 24 intra-segment offset bits, it clears bits 56–63 of the 64-bit LSN. For any LSN whose log-id has its high byte set (log-id ≥ 0x01000000), the result no longer equals _seg * WAL_SEG_SIZE, disagrees with _seg/from_walfile_name, and breaks the walfile_name round-trip — which also corrupts next_walfile_start_lsn/previous_walfile_start_lsn used during WAL iteration. Every other method on LSN (_seg, from_walfile_name, walfile_name) handles the full 64-bit LSN; only this one truncates.

In practice the divergence only appears at LSNs far beyond what real clusters reach, so this is an invariant-correctness fix rather than a live-impact one; behaviour is unchanged for realistic LSNs.

Fix

Derive the segment start from the segment number (self._seg * WAL_SEG_SIZE) so it can no longer drift from the rest of the segment arithmetic. Adds a regression test for a structurally valid WAL file name with a high-byte log-id.

LSN.walfile_start_lsn should return the start LSN of the WAL segment that
contains this LSN, i.e. `self._seg * WAL_SEG_SIZE` (the LSN with its
intra-segment offset cleared).

It instead computed `self.lsn & 0xFFFFFFFF000000`. That mask is one hex
digit pair too short: as well as clearing the low 24 offset bits it clears
bits 56-63 of the 64-bit LSN. For any LSN whose log-id has its high byte set
(log-id >= 0x01000000) the result no longer equals `_seg * WAL_SEG_SIZE`,
disagrees with `_seg`/`from_walfile_name`, and breaks the
`walfile_name` round trip (also corrupting next_/previous_walfile_start_lsn,
which are used during WAL iteration). Behaviour is unchanged for the LSN
range real clusters reach.

Derive the segment start from the segment number so it can no longer drift
from the other segment arithmetic. Add a regression test covering a
structurally valid WAL file name with a high-byte log-id.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant