Re: hio.c does visibilitymap_pin()/IO while holding buffer lock - Mailing list pgsql-hackers

From Andres Freund
Subject Re: hio.c does visibilitymap_pin()/IO while holding buffer lock
Date
Msg-id 20230329012102.zpviu2e7kyfrovxn@awork3.anarazel.de
Whole thread Raw
In response to Re: hio.c does visibilitymap_pin()/IO while holding buffer lock  (Andres Freund <andres@anarazel.de>)
Responses Re: hio.c does visibilitymap_pin()/IO while holding buffer lock  (Andres Freund <andres@anarazel.de>)
List pgsql-hackers
Hi,

On 2023-03-25 11:17:07 -0700, Andres Freund wrote:
> I don't see how that's easily possible with the current lock ordering
> rules. At least without giving up using RBM_ZERO_AND_LOCK for extending or
> stuffing even more things to happen with the the extension lock held, which I
> don't think we want to. I don't think INSERT_FROZEN is worth that price.

I think I might have been thinking of this too narrowly. It's extremely
unlikely that another backend would discover the page. And we can use
visibilitymap_pin_ok() to amortize the cost to almost nothing - there's a lot
of bits in an 8k block...


Here's a draft patch.


The bulk relation patch I am polishing has a similar issue, except that there
the problem is inserting into the FSM, instead of pinning a VM pageabout the
FSM. Hence the patch above makes the infrastructure a bit more general than
required for the HEAP_INSERT_FROZEN case alone (where we currently shouldn't
ever have a valid otherBuffer).


The way the parameter ordering for GetVisibilityMapPins() works make it
somewhat unwieldy - see e.g the existing
        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 I now duplicated in yet another place.

Perhaps we just ought to switch buffer1/block1 with buffer2/block2 inside
GetVisibilityMapPins(), to avoid duplicating that code elsewhere?


Because we now track whether the *targetBuffer* was ever unlocked, we can be a
bit more narrow about the possibility of there not being sufficient space.


The patch could be narrowed for backpatching. But as there's likely no
practical problem at this point, I wouldn't want to backpatch anyway?

Greetings,

Andres Freund

Attachment

pgsql-hackers by date:

Previous
From: "Hayato Kuroda (Fujitsu)"
Date:
Subject: RE: PGdoc: add missing ID attribute to create_subscription.sgml
Next
From: Michael Paquier
Date:
Subject: Re: allow_in_place_tablespaces vs. pg_basebackup