Fix setting next multixid's offset at offset wraparound
authorHeikki Linnakangas <[email protected]>
Fri, 5 Dec 2025 09:32:38 +0000 (11:32 +0200)
committerHeikki Linnakangas <[email protected]>
Fri, 5 Dec 2025 09:37:06 +0000 (11:37 +0200)
In commit 789d65364c, we started updating the next multixid's offset
too when recording a multixid, so that it can always be used to
calculate the number of members. I got it wrong at offset wraparound:
we need to skip over offset 0. Fix that.

Discussion: https://www.postgresql.org/message-id/d9996478-389a-4340-8735-bfad456b313c@iki.fi
Backpatch-through: 14

src/backend/access/transam/multixact.c

index 920ec582b6dabaf900e228cf697b9a15d32880a5..e80e4b198e127e1e9d5d8e9b77dce1db3f9c4119 100644 (file)
@@ -875,6 +875,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
    int         next_pageno;
    int         next_entryno;
    MultiXactOffset *next_offptr;
+   MultiXactOffset next_offset;
 
    LWLockAcquire(MultiXactOffsetSLRULock, LW_EXCLUSIVE);
 
@@ -961,11 +962,15 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
        next_offptr += next_entryno;
    }
 
-   if (*next_offptr != offset + nmembers)
+   /* Like in GetNewMultiXactId(), skip over offset 0 */
+   next_offset = offset + nmembers;
+   if (next_offset == 0)
+       next_offset = 1;
+   if (*next_offptr != next_offset)
    {
        /* should already be set to the correct value, or not at all */
        Assert(*next_offptr == 0);
-       *next_offptr = offset + nmembers;
+       *next_offptr = next_offset;
        MultiXactOffsetCtl->shared->page_dirty[slotno] = true;
    }