8000 Protect against torn pages when deleting GIN list pages. · larkly/postgres-docker@be78305 · GitHub
[go: up one dir, main page]

Skip to content

Commit be78305

Browse files
committed
Protect against torn pages when deleting GIN list pages.
To-be-deleted list pages contain no useful information, as they are being deleted, but we must still protect the writes from being torn by a crash after a partial write. To do that, re-initialize the pages on WAL replay. Jeff Janes caught this with a test program to test partial writes. Backpatch to all supported versions.
1 parent 664ac3d commit be78305

File tree

1 file changed

+13
-14
lines changed

1 file changed

+13
-14
lines changed

src/backend/access/gin/ginxlog.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -650,25 +650,24 @@ ginRedoDeleteListPages(XLogRecPtr 10000 lsn, XLogRecord *record)
650650
PageSetTLI(metapage, ThisTimeLineID);
651651
MarkBufferDirty(metabuffer);
652652

653+
/*
654+
* No full-page images are taken of the deleted pages. Instead, they are
655+
* re-initialized as empty, deleted pages.
656+
*/
653657
for (i = 0; i < data->ndeleted; i++)
654658
{
655-
Buffer buffer = XLogReadBuffer(data->node, data->toDelete[i], false);
659+
Buffer buffer;
660+
Page page;
656661

657-
if (BufferIsValid(buffer))
658-
{
659-
Page page = BufferGetPage(buffer);
660-
661-
if (!XLByteLE(lsn, PageGetLSN(page)))
662-
{
663-
GinPageGetOpaque(page)->flags = GIN_DELETED;
662+
buffer = XLogReadBuffer(data->node, data->toDelete[i], true);
663+
page = BufferGetPage(buffer);
664+
GinInitBuffer(buffer, GIN_DELETED);
664665

665-
PageSetLSN(page, lsn);
666-
PageSetTLI(page, ThisTimeLineID);
667-
MarkBufferDirty(buffer);
668-
}
666+
PageSetLSN(page, lsn);
667+
PageSetTLI(page, ThisTimeLineID);
668+
MarkBufferDirty(buffer);
669669

670-
UnlockReleaseBuffer(buffer);
671-
}
670+
UnlockReleaseBuffer(buffer);
672671
}
673672
UnlockReleaseBuffer(metabuffer);
674673
}

0 commit comments

Comments
 (0)
0