From 0e379ca25a6eb5d658a2241be06ff6f45369171e Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 11 Mar 2026 11:48:59 +0200
Subject: [PATCH v5 2/2] make the errdetail on multixact members more detailed

(to be squashed)
---
 src/backend/access/transam/multixact.c | 29 +++++++++++++++++++-------
 src/tools/pgindent/typedefs.list       |  1 +
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index abde1750189..30e04080b00 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -313,6 +313,14 @@ static void mXactCachePut(MultiXactId multi, int nmembers,
 						  MultiXactMember *members);
 
 /* management of SLRU infrastructure */
+
+/* opaque_data type for MultiXactMemberIoErrorDetail */
+typedef struct MultiXactOffsetSlruReadContext
+{
+	MultiXactId multi;
+	MultiXactOffset offset;
+} MultiXactOffsetSlruReadContext;
+
 static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
 static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
 static int	MultiXactOffsetIoErrorDetail(const void *opaque_data);
@@ -907,6 +915,8 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 
 		if (pageno != prev_pageno)
 		{
+			MultiXactOffsetSlruReadContext slru_read_context = {multi, offset};
+
 			/*
 			 * MultiXactMember SLRU page is changed so check if this new page
 			 * fall into the different SLRU bank then release the old bank's
@@ -922,7 +932,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 				prevlock = lock;
 			}
 			slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true,
-									   &offset);
+									   &slru_read_context);
 			prev_pageno = pageno;
 		}
 
@@ -1334,6 +1344,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 
 		if (pageno != prev_pageno)
 		{
+			MultiXactOffsetSlruReadContext slru_read_context = {multi, offset};
 			LWLock	   *newlock;
 
 			/*
@@ -1349,9 +1360,8 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 				LWLockAcquire(newlock, LW_EXCLUSIVE);
 				lock = newlock;
 			}
-
 			slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true,
-									   &offset);
+									   &slru_read_context);
 			prev_pageno = pageno;
 		}
 
@@ -1962,6 +1972,7 @@ TrimMultiXact(void)
 	flagsoff = MXOffsetToFlagsOffset(offset);
 	if (flagsoff != 0)
 	{
+		MultiXactOffsetSlruReadContext slru_read_context = {InvalidMultiXactId, offset};
 		int			slotno;
 		TransactionId *xidptr;
 		int			memberoff;
@@ -1969,7 +1980,7 @@ TrimMultiXact(void)
 
 		LWLockAcquire(lock, LW_EXCLUSIVE);
 		memberoff = MXOffsetToMemberOffset(offset);
-		slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, &offset);
+		slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, &slru_read_context);
 		xidptr = (TransactionId *)
 			(MultiXactMemberCtl->shared->page_buffer[slotno] + memberoff);
 
@@ -2825,10 +2836,14 @@ MultiXactOffsetIoErrorDetail(const void *opaque_data)
 static int
 MultiXactMemberIoErrorDetail(const void *opaque_data)
 {
-	MultiXactOffset mxoff = *(const MultiXactOffset *) opaque_data;
+	const MultiXactOffsetSlruReadContext *context = opaque_data;
 
-	return errdetail("Could not access multixact member at offset %" PRIu64 ".",
-					 mxoff);
+	if (MultiXactIdIsValid(context->multi))
+		return errdetail("Could not access member of multixact %u at offset %" PRIu64 ".",
+						 context->multi, context->offset);
+	else
+		return errdetail("Could not access multixact member at offset %" PRIu64 ".",
+						 context->offset);
 }
 
 /*
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 3da19d41413..951c0574e52 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1749,6 +1749,7 @@ MultiXactId
 MultiXactMember
 MultiXactOffset
 MultiXactOffset32
+MultiXactOffsetSlruReadContext
 MultiXactStateData
 MultiXactStatus
 MultirangeIOData
-- 
2.47.3

