Skip to content

Commit bba9003

Browse files
committed
hio: Relax rules for calling GetVisibilityMapPins()
GetVisibilityMapPins() insisted on the buffer1/buffer2 being in a specific order. This required checks at the callsite. As a subsequent patch will add another callsite, move related logic into GetVisibilityMapPins(). Discussion: https://postgr.es/m/20230403190030.fk2frxv6faklrseb@awork3.anarazel.de
1 parent 00beecf commit bba9003

File tree

1 file changed

+26
-11
lines changed
  • src/backend/access/heap

1 file changed

+26
-11
lines changed

src/backend/access/heap/hio.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ ReadBufferBI(Relation relation, BlockNumber targetBlock,
131131
* For each heap page which is all-visible, acquire a pin on the appropriate
132132
* visibility map page, if we haven't already got one.
133133
*
134-
* buffer2 may be InvalidBuffer, if only one buffer is involved. buffer1
135-
* must not be InvalidBuffer. If both buffers are specified, block1 must
136-
* be less than block2.
134+
* To avoid complexity in the callers, either buffer1 or buffer2 may be
135+
* InvalidBuffer if only one buffer is involved. For the same reason, block2
136+
* may be smaller than block1.
137137
*/
138138
static void
139139
GetVisibilityMapPins(Relation relation, Buffer buffer1, Buffer buffer2,
@@ -143,6 +143,26 @@ GetVisibilityMapPins(Relation relation, Buffer buffer1, Buffer buffer2,
143143
bool need_to_pin_buffer1;
144144
bool need_to_pin_buffer2;
145145

146+
/*
147+
* Swap buffers around to handle case of a single block/buffer, and to
148+
* handle if lock ordering rules require to lock block2 first.
149+
*/
150+
if (!BufferIsValid(buffer1) ||
151+
(BufferIsValid(buffer2) && block1 > block2))
152+
{
153+
Buffer tmpbuf = buffer1;
154+
Buffer *tmpvmbuf = vmbuffer1;
155+
BlockNumber tmpblock = block1;
156+
157+
buffer1 = buffer2;
158+
vmbuffer1 = vmbuffer2;
159+
block1 = block2;
160+
161+
buffer2 = tmpbuf;
162+
vmbuffer2 = tmpvmbuf;
163+
block2 = tmpblock;
164+
}
165+
146166
Assert(BufferIsValid(buffer1));
147167
Assert(buffer2 == InvalidBuffer || block1 <= block2);
148168

@@ -502,14 +522,9 @@ RelationGetBufferForTuple(Relation relation, Size len,
502522
* done a bit of extra work for no gain, but there's no real harm
503523
* done.
504524
*/
505-
if (otherBuffer == InvalidBuffer || targetBlock <= otherBlock)
506-
GetVisibilityMapPins(relation, buffer, otherBuffer,
507-
targetBlock, otherBlock, vmbuffer,
508-
vmbuffer_other);
509-
else
510-
GetVisibilityMapPins(relation, otherBuffer, buffer,
511-
otherBlock, targetBlock, vmbuffer_other,
512-
vmbuffer);
525+
GetVisibilityMapPins(relation, buffer, otherBuffer,
526+
targetBlock, otherBlock, vmbuffer,
527+
vmbuffer_other);
513528

514529
/*
515530
* Now we can check to see if there's enough free space here. If so,

0 commit comments

Comments
 (0)