Skip to content

Commit dfe5c00

Browse files
macdicepull[bot]
authored andcommitted
Fix race in SSI interaction with gin fast path.
The ginfast.c code previously checked for conflicts in before locking the relevant buffer, leaving a window where a RW conflict could be missed. Re-order. There was also a place where buffer ID and block number were confused while trying to predicate-lock a page, noted by visual inspection. Back-patch to all supported releases. Fixes one more problem discovered with the reproducer from bug #17949, in this case when Dmitry tried other index types. Reported-by: Artem Anisimov <artem.anisimov.255@gmail.com> Reported-by: Dmitry Dolgov <9erthalion6@gmail.com> Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Discussion: https://postgr.es/m/17949-a0f17035294a55e2%40postgresql.org
1 parent 87955ca commit dfe5c00

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

src/backend/access/gin/ginfast.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,10 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
245245
/*
246246
* An insertion to the pending list could logically belong anywhere in the
247247
* tree, so it conflicts with all serializable scans. All scans acquire a
248-
* predicate lock on the metabuffer to represent that.
248+
* predicate lock on the metabuffer to represent that. Therefore we'll
249+
* check for conflicts in, but not until we have the page locked and are
250+
* ready to modify the page.
249251
*/
250-
CheckForSerializableConflictIn(index, NULL, GIN_METAPAGE_BLKNO);
251252

252253
if (collector->sumsize + collector->ntuples * sizeof(ItemIdData) > GinListPageSize)
253254
{
@@ -291,6 +292,8 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
291292
LockBuffer(metabuffer, GIN_EXCLUSIVE);
292293
metadata = GinPageGetMeta(metapage);
293294

295+
CheckForSerializableConflictIn(index, NULL, GIN_METAPAGE_BLKNO);
296+
294297
if (metadata->head == InvalidBlockNumber)
295298
{
296299
/*
@@ -353,6 +356,8 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
353356
char *ptr;
354357
char *collectordata;
355358

359+
CheckForSerializableConflictIn(index, NULL, GIN_METAPAGE_BLKNO);
360+
356361
buffer = ReadBuffer(index, metadata->tail);
357362
LockBuffer(buffer, GIN_EXCLUSIVE);
358363
page = BufferGetPage(buffer);

src/backend/access/gin/ginget.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack,
140140
* Predicate lock entry leaf page, following pages will be locked by
141141
* moveRightIfItNeeded()
142142
*/
143-
PredicateLockPage(btree->index, stack->buffer, snapshot);
143+
PredicateLockPage(btree->index,
144+
BufferGetBlockNumber(stack->buffer),
145+
snapshot);
144146

145147
for (;;)
146148
{

0 commit comments

Comments
 (0)