Hi all,
(CCing Heikki as the committer of commit bd8d9c9bdfa)
Commit bd8d9c9bdfa widened MultiXactOffset to uint64, but I found that
pg_upgrade still reads it as a uint32 value when reading the
pg_controldata continents:
else if ((p = strstr(bufin, "Latest checkpoint's NextMultiOffset:")) != NULL)
{
:
p++; /* remove ':' char */
cluster->controldata.chkpnt_nxtmxoff = str2uint(p);
I think it should use strtou64() instead. The attached 0001 patch
fixes it. It introduces str2uint64() as other fields are read by a
similar helper function str2uint().
Also, when checking other similar codes around the new
MultiXactOffset, I found that pg_control_checkpoint() still reports
the value as an xid. I think we should report it as bigint instead.
What do you think? The attached 0002 patch fixes it.
Regards,
--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
From 4389bc165db2ab33feab21e531bc6a1b7f3a546f Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <[email protected]>
Date: Wed, 26 Aug 2026 17:44:33 -0700
Subject: [PATCH 2/2] Report next_multi_offset as bigint in
pg_control_checkpoint().
XXX Bump catalog version.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch-through: 19
---
doc/src/sgml/func/func-info.sgml | 2 +-
src/backend/utils/misc/pg_controldata.c | 2 +-
src/include/catalog/pg_proc.dat | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml
index e3c05e8b933..2f03766b67a 100644
--- a/doc/src/sgml/func/func-info.sgml
+++ b/doc/src/sgml/func/func-info.sgml
@@ -3458,7 +3458,7 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
<row>
<entry><structfield>next_multi_offset</structfield></entry>
- <entry><type>xid</type></entry>
+ <entry><type>bigint</type></entry>
</row>
<row>
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index ab74d169c96..9014f0953e9 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -130,7 +130,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
nulls[9] = false;
- values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
+ values[10] = Int64GetDatum(ControlFile->checkPointCopy.nextMultiOffset);
nulls[10] = false;
values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f5867349d14..805a579080d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12346,7 +12346,7 @@
descr => 'pg_controldata checkpoint state information as a function',
proname => 'pg_control_checkpoint', provolatile => 'v',
prorettype => 'record', proargtypes => '',
- proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,int4,timestamptz}',
+ proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,bool,text,oid,xid,int8,xid,oid,xid,xid,oid,xid,xid,int4,timestamptz}',
proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,logical_decoding,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,data_page_checksum_version,checkpoint_time}',
prosrc => 'pg_control_checkpoint' },
--
2.55.0
From 956b715e45e511b48d5d486f63b2f75968d5df90 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <[email protected]>
Date: Wed, 26 Aug 2026 17:44:02 -0700
Subject: [PATCH 1/2] pg_upgrade: Read nextMultiOffset as a 64-bit value.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch-through: 19
---
src/bin/pg_upgrade/controldata.c | 2 +-
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/util.c | 11 +++++++++++
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c
index fd772ba4f38..8c69329805b 100644
--- a/src/bin/pg_upgrade/controldata.c
+++ b/src/bin/pg_upgrade/controldata.c
@@ -352,7 +352,7 @@ get_control_data(ClusterInfo *cluster)
pg_fatal("%d: controldata retrieval problem", __LINE__);
p++; /* remove ':' char */
- cluster->controldata.chkpnt_nxtmxoff = str2uint(p);
+ cluster->controldata.chkpnt_nxtmxoff = str2uint64(p);
got_mxoff = true;
}
else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index ccd1ac0d013..92607daace5 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -496,6 +496,7 @@ void cleanup_output_dirs(void);
void prep_status(const char *fmt, ...) pg_attribute_printf(1, 2);
void prep_status_progress(const char *fmt, ...) pg_attribute_printf(1, 2);
unsigned int str2uint(const char *str);
+uint64 str2uint64(const char *str);
/* version.c */
diff --git a/src/bin/pg_upgrade/util.c b/src/bin/pg_upgrade/util.c
index 08d6385b512..e7d7ab56445 100644
--- a/src/bin/pg_upgrade/util.c
+++ b/src/bin/pg_upgrade/util.c
@@ -353,3 +353,14 @@ str2uint(const char *str)
{
return strtoul(str, NULL, 10);
}
+
+/*
+ * str2uint64()
+ *
+ * convert string to uint64
+ */
+uint64
+str2uint64(const char *str)
+{
+ return strtou64(str, NULL, 10);
+}
--
2.55.0