Hi,

On Sat, Sep 12, 2026 at 4:52 AM Paul Kim <[email protected]> wrote:
>
> Whether XactLastRecEnd
> receiving a "start of the next record" position deserves a fix of its
> own is a fair follow-up question; the other consumers appear to cope
> with it, so I kept it out of this patch series.

Thanks for sending the v4 patches. TBH, fixing it in the WAL writer
looks like fixing the symptom of the issue. That approach also seems
to have a problem. XLogCtl->asyncXactLSN doesn't change until new WAL
is written, so the WAL writer keeps using the old value (B+40) and
keeps logging "request to flush past end of generated WAL" messages.

How about adjusting EndPos itself to the start of the segment (before
the page header) using XLogBytePosToEndRecPtr in this case, where the
switch WAL record falls right on the segment boundary, something like
the attached? This way, the switch record's EndPos (B+40) no longer
goes into XactLastRecEnd and XLogCtl->asyncXactLSN, and from there
into the WAL writer and WaitXLogInsertionsToFinish(). It fixes the
issue for me and the regression tests pass.

--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com
From 3fe41b9281855e37458385a7172f984f9f974924 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <[email protected]>
Date: Fri, 9 Oct 2026 04:16:25 +0000
Subject: [PATCH] Fix end LSN reported for an xlog-switch record ending on a
 page boundary

A page header size is added to the end of an xlog-switch record
even when the record ends exactly on a page boundary and crosses
no header. At a segment boundary that puts the end past the end of
reserved WAL. The position then goes into the asynchronous commit
LSN, and from there into the WAL writer, which keeps logging
"request to flush past end of generated WAL" and reports write and
flush positions for WAL that was never written.

Adjust the end position to the start of the segment (before the
page header) using XLogBytePosToEndRecPtr(), the way it is done
for any other record. The bad position then no longer goes into
the asynchronous commit LSN or the WAL writer.

More blah.
---
 src/backend/access/transam/xlog.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index afbe068cd0a..72ec58551ed 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -1077,21 +1077,14 @@ XLogInsertRecord(XLogRecData *rdata,
 		/*
 		 * Even though we reserved the rest of the segment for us, which is
 		 * reflected in EndPos, we return a pointer to just the end of the
-		 * xlog-switch record.
+		 * xlog-switch record. When the record falls right on the segment
+		 * boundary, EndPos is adjusted to the start of the segment (before
+		 * the page header), so that it doesn't go past the end of reserved
+		 * WAL.
 		 */
 		if (inserted)
-		{
-			EndPos = StartPos + SizeOfXLogRecord;
-			if (StartPos / XLOG_BLCKSZ != EndPos / XLOG_BLCKSZ)
-			{
-				uint64		offset = XLogSegmentOffset(EndPos, wal_segment_size);
-
-				if (offset == EndPos % XLOG_BLCKSZ)
-					EndPos += SizeOfXLogLongPHD;
-				else
-					EndPos += SizeOfXLogShortPHD;
-			}
-		}
+			EndPos = XLogBytePosToEndRecPtr(XLogRecPtrToBytePos(StartPos) +
+											MAXALIGN(SizeOfXLogRecord));
 	}
 
 	/* Process any flush progress published while making room for the record. */
-- 
2.47.3

Reply via email to