0001-rough-draft-of-skipping-bogus-offsets.patch.txt

text/plain

Filename: 0001-rough-draft-of-skipping-bogus-offsets.patch.txt
Type: text/plain
Part: 0
Message: Re: POC: make mxidoff 64 bits
From c2ccb107bef898420e6417c37d56c6b30578d28f Mon Sep 17 00:00:00 2001
From: Maxim Orlov <orlovmg@gmail.com>
Date: Thu, 4 Dec 2025 17:02:35 +0300
Subject: [PATCH] rough draft of skipping bogus offsets

---
 src/bin/pg_upgrade/multixact_old.c | 38 ++++++++++++++++++++++++------
 src/bin/pg_upgrade/multixact_old.h |  2 +-
 src/bin/pg_upgrade/pg_upgrade.c    | 15 ++++++------
 3 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/src/bin/pg_upgrade/multixact_old.c b/src/bin/pg_upgrade/multixact_old.c
index 529eeeb93b6..685bfaeff82 100644
--- a/src/bin/pg_upgrade/multixact_old.c
+++ b/src/bin/pg_upgrade/multixact_old.c
@@ -136,7 +136,7 @@ AllocOldMultiXactRead(char *pgdata, MultiXactId nextMulti,
  * - Because there's no concurrent activity, We don't need to worry about
  *   locking and some corner cases.
  */
-void
+bool
 GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi,
 							  TransactionId *result, MultiXactStatus *status)
 {
@@ -189,7 +189,18 @@ GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi,
 	offptr += entryno;
 	offset = *offptr;
 
-	Assert(offset != 0);
+	if (offset == 0)
+	{
+		pg_log(PG_WARNING, "multixact %u, offset is empty", multi);
+		return false;
+	}
+#if 0
+	if ( <more checks> )
+	{
+		pg_log(PG_WARNING, "multixact %u, offset is bogus", multi);
+		return false;
+	}
+#endif
 
 	/*
 	 * Use the same increment rule as GetNewMultiXactId(), that is, don't
@@ -224,9 +235,13 @@ GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi,
 
 		/*
 		 * Corner case 2: next multixact is still being filled in, this cannot
-		 * happen during upgrade.
+		 * happen during upgrade, but if it does, complain.
 		 */
-		Assert(nextMXOffset != 0);
+		if (nextMXOffset == 0)
+		{
+			pg_log(PG_WARNING, "multixact next to %u is empty", multi);
+			return false;
+		}
 
 		length = nextMXOffset - offset;
 	}
@@ -272,8 +287,11 @@ GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi,
 		{
 			/* sanity check */
 			if (result_isupdate)
-				pg_fatal("multixact %u has more than one updating member",
-						 multi);
+			{
+				pg_log(PG_WARNING,
+					   "multixact %u has more than one updating member", multi);
+				return false;
+			}
 			result_xid = *xactptr;
 			result_isupdate = true;
 		}
@@ -282,11 +300,17 @@ GetOldMultiXactIdSingleMember(OldMultiXactReader *state, MultiXactId multi,
 	}
 
 	/* A multixid with zero members should not happen */
-	Assert(TransactionIdIsValid(result_xid));
+	if (!TransactionIdIsValid(result_xid))
+	{
+		pg_log(PG_WARNING, "multixact %u have zero members", multi);
+		return false;
+	}
 
 	*result = result_xid;
 	*status = result_isupdate ? MultiXactStatusUpdate :
 		MultiXactStatusForKeyShare;
+
+	return true;
 }
 
 /*
diff --git a/src/bin/pg_upgrade/multixact_old.h b/src/bin/pg_upgrade/multixact_old.h
index 4f9e086a1fb..b7352159d83 100644
--- a/src/bin/pg_upgrade/multixact_old.h
+++ b/src/bin/pg_upgrade/multixact_old.h
@@ -29,7 +29,7 @@ typedef struct OldMultiXactReader
 extern OldMultiXactReader *AllocOldMultiXactRead(char *pgdata,
 												 MultiXactId nextMulti,
 												 OldMultiXactOffset nextOffset);
-extern void GetOldMultiXactIdSingleMember(OldMultiXactReader *state,
+extern bool GetOldMultiXactIdSingleMember(OldMultiXactReader *state,
 										  MultiXactId multi,
 										  TransactionId *result,
 										  MultiXactStatus *status);
diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c
index ff937b9e104..c5da56fe785 100644
--- a/src/bin/pg_upgrade/pg_upgrade.c
+++ b/src/bin/pg_upgrade/pg_upgrade.c
@@ -832,14 +832,15 @@ convert_multixacts(MultiXactId from_multi, MultiXactId to_multi)
 			 * one updating one, or if there was no update, arbitrarily the
 			 * first locking xid.
 			 */
-			GetOldMultiXactIdSingleMember(old_reader, multi, &xid, &status);
+			if (GetOldMultiXactIdSingleMember(old_reader, multi, &xid, &status))
+			{
+				/* Write it out in new format */
+				member.xid = xid;
+				member.status = status;
+				RecordNewMultiXact(new_writer, next_offset, multi, 1, &member);
+				next_offset += 1;
+			}
 
-			/* Write it out in new format */
-			member.xid = xid;
-			member.status = status;
-			RecordNewMultiXact(new_writer, next_offset, multi, 1, &member);
-
-			next_offset += 1;
 			multi++;
 			/* handle wraparound */
 			if (multi < FirstMultiXactId)
-- 
2.43.0