Re: PANIC: wrong buffer passed to visibilitymap_clear - Mailing list pgsql-hackers

From Andres Freund
Subject Re: PANIC: wrong buffer passed to visibilitymap_clear
Date
Msg-id 20210409232739.sazp5p4xnnagrusa@alap3.anarazel.de
Whole thread Raw
In response to PANIC: wrong buffer passed to visibilitymap_clear  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: PANIC: wrong buffer passed to visibilitymap_clear  (Andres Freund <andres@anarazel.de>)
List pgsql-hackers
Hi,

On 2021-04-09 18:40:27 -0400, Tom Lane wrote:
> Buildfarm members spurfowl[1] and thorntail[2] have each shown $SUBJECT
> once in the past two days.  The circumstances are not quite the same;
> spurfowl's failure is in autovacuum while thorntail's is in a manual
> VACUUM command.  Still, it seems clear that there's a recently-introduced
> bug here somewhere.  I don't see any obvious candidate for the culprit,
> though.  Any ideas?

commit 7ab96cf6b312cfcd79cdc1a69c6bdb75de0ed30f
Author: Peter Geoghegan <pg@bowt.ie>
Date:   2021-04-06 07:49:39 -0700

    Refactor lazy_scan_heap() loop.

or some of the other changes in the vicinity could be related. There's
some changes when pages are marked as AllVisible, when their free space
is tracked etc.


Just looking at the code in heap_update: I'm a bit confused about
RelationGetBufferForTuple()'s vmbuffer and vmbuffer_other
arguments. It looks like it's not at all clear which of the two
arguments will have the vmbuffer for which of the pages?

        if (otherBuffer == InvalidBuffer || targetBlock <= otherBlock)
            GetVisibilityMapPins(relation, buffer, otherBuffer,
                                 targetBlock, otherBlock, vmbuffer,
                                 vmbuffer_other);
        else
            GetVisibilityMapPins(relation, otherBuffer, buffer,
                                 otherBlock, targetBlock, vmbuffer_other,
                                 vmbuffer);

Which then would make any subsequent use of vmbuffer vs vmbuffer_new in
heap_update() bogus? Because clearly that code associates vmbuffer /
vmbuffer_new with the respective page?

    /* clear PD_ALL_VISIBLE flags, reset all visibilitymap bits */
    if (PageIsAllVisible(BufferGetPage(buffer)))
    {
        all_visible_cleared = true;
        PageClearAllVisible(BufferGetPage(buffer));
        visibilitymap_clear(relation, BufferGetBlockNumber(buffer),
                            vmbuffer, VISIBILITYMAP_VALID_BITS);
    }
    if (newbuf != buffer && PageIsAllVisible(BufferGetPage(newbuf)))
    {
        all_visible_cleared_new = true;
        PageClearAllVisible(BufferGetPage(newbuf));
        visibilitymap_clear(relation, BufferGetBlockNumber(newbuf),
                            vmbuffer_new, VISIBILITYMAP_VALID_BITS);
    }

Greetings,

Andres Freund



pgsql-hackers by date:

Previous
From: Peter Geoghegan
Date:
Subject: Re: PANIC: wrong buffer passed to visibilitymap_clear
Next
From: Andres Freund
Date:
Subject: Re: PANIC: wrong buffer passed to visibilitymap_clear