On Tue, Oct 28, 2025 at 07:33:00PM +0900, Shinya Kato wrote: > I investigated previous discussions and found [0]. This thread > mentioned that XLogInsert() calls XLogRecordAssemble() multiple times > in its do-while loop, so the value might be invalid. > > Based on the discussion above, it seems my previous patch also has the > same issue. > > [0] https://www.postgresql.org/message-id/20200329121944.GA79261%40nol
Dammit, you are right. I didn't see through this one. Even on HEAD it is true that we may trigger an early exit of XLogInsertRecord() and call XLogRecordAssemble() multiple times with a different FPI setup. So we cannot do direct manipulations of pgWalUsage in XLogRecordAssemble(), we must do these once the record is inserted. I'll clean up that tomorrow, which can be summarized as something like the attached (quick fix, need to double-check). -- Michael
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index d12798be3d80..a12757e46e5b 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -202,6 +202,7 @@ extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
XLogRecPtr fpw_lsn,
uint8 flags,
int num_fpi,
+ uint64 fpi_bytes,
bool topxid_included);
extern void XLogFlush(XLogRecPtr record);
extern bool XLogBackgroundFlush(void);
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index eceab3412558..fd91bcd68ecd 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -749,6 +749,7 @@ XLogInsertRecord(XLogRecData *rdata,
XLogRecPtr fpw_lsn,
uint8 flags,
int num_fpi,
+ uint64 fpi_bytes,
bool topxid_included)
{
XLogCtlInsert *Insert = &XLogCtl->Insert;
@@ -1081,6 +1082,7 @@ XLogInsertRecord(XLogRecData *rdata,
pgWalUsage.wal_bytes += rechdr->xl_tot_len;
pgWalUsage.wal_records++;
pgWalUsage.wal_fpi += num_fpi;
+ pgWalUsage.wal_fpi_bytes += fpi_bytes;
/* Required for the flush of pending stats WAL data */
pgstat_report_fixed = true;
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index b3abf386f801..58cb4b1b00c9 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -139,6 +139,7 @@ static MemoryContext xloginsert_cxt;
static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info,
XLogRecPtr RedoRecPtr, bool doPageWrites,
XLogRecPtr *fpw_lsn, int *num_fpi,
+ uint64 *fpi_bytes,
bool *topxid_included);
static bool XLogCompressBackupBlock(const PageData *page, uint16 hole_offset,
uint16 hole_length, void *dest, uint16 *dlen);
@@ -512,6 +513,7 @@ XLogInsert(RmgrId rmid, uint8 info)
XLogRecPtr fpw_lsn;
XLogRecData *rdt;
int num_fpi = 0;
+ uint64 fpi_bytes = 0;
/*
* Get values needed to decide whether to do full-page writes. Since
@@ -521,10 +523,11 @@ XLogInsert(RmgrId rmid, uint8 info)
GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
- &fpw_lsn, &num_fpi, &topxid_included);
+ &fpw_lsn, &num_fpi, &fpi_bytes,
+ &topxid_included);
EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
- topxid_included);
+ fpi_bytes, topxid_included);
} while (EndPos == InvalidXLogRecPtr);
XLogResetInsertion();
@@ -562,7 +565,8 @@ XLogSimpleInsertInt64(RmgrId rmid, uint8 info, int64 value)
static XLogRecData *
XLogRecordAssemble(RmgrId rmid, uint8 info,
XLogRecPtr RedoRecPtr, bool doPageWrites,
- XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
+ XLogRecPtr *fpw_lsn, int *num_fpi, uint64 *fpi_bytes,
+ bool *topxid_included)
{
XLogRecData *rdt;
uint64 total_len = 0;
@@ -800,8 +804,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
total_len += bimg.length;
/* Track the WAL full page images in bytes */
- pgWalUsage.wal_fpi_bytes += bimg.length;
- pgstat_report_fixed = true;
+ *fpi_bytes += bimg.length;
}
if (needs_data)
signature.asc
Description: PGP signature
