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.
This commit is contained in:
parent
664ac3de7f
commit
be7830596f
|
@ -650,25 +650,24 @@ ginRedoDeleteListPages(XLogRecPtr lsn, XLogRecord *record)
|
|||
PageSetTLI(metapage, ThisTimeLineID);
|
||||
MarkBufferDirty(metabuffer);
|
||||
|
||||
/*
|
||||
* No full-page images are taken of the deleted pages. Instead, they are
|
||||
* re-initialized as empty, deleted pages.
|
||||
*/
|
||||
for (i = 0; i < data->ndeleted; i++)
|
||||
{
|
||||
Buffer buffer = XLogReadBuffer(data->node, data->toDelete[i], false);
|
||||
Buffer buffer;
|
||||
Page page;
|
||||
|
||||
if (BufferIsValid(buffer))
|
||||
{
|
||||
Page page = BufferGetPage(buffer);
|
||||
buffer = XLogReadBuffer(data->node, data->toDelete[i], true);
|
||||
page = BufferGetPage(buffer);
|
||||
GinInitBuffer(buffer, GIN_DELETED);
|
||||
|
||||
if (!XLByteLE(lsn, PageGetLSN(page)))
|
||||
{
|
||||
GinPageGetOpaque(page)->flags = GIN_DELETED;
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
MarkBufferDirty(buffer);
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
MarkBufferDirty(buffer);
|
||||
}
|
||||
|
||||
UnlockReleaseBuffer(buffer);
|
||||
}
|
||||
UnlockReleaseBuffer(buffer);
|
||||
}
|
||||
UnlockReleaseBuffer(metabuffer);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue