Skip to content

Commit

Permalink
Fix bug in GenericXLogFinish().
Browse files Browse the repository at this point in the history
Mark the buffers dirty before writing WAL.

Discussion: https://postgr.es/m/25104133-7df8-cae3-b9a2-1c0aaa1c094a@iki.fi
Reviewed-by: Heikki Linnakangas
Backpatch-through: 11
  • Loading branch information
jeff-davis committed Oct 10, 2023
1 parent 694d670 commit 04f0baa
Showing 1 changed file with 26 additions and 30 deletions.
56 changes: 26 additions & 30 deletions src/backend/access/transam/generic_xlog.c
Expand Up @@ -342,6 +342,10 @@ GenericXLogFinish(GenericXLogState *state)

START_CRIT_SECTION();

/*
* Compute deltas if necessary, write changes to buffers, mark
* buffers dirty, and register changes.
*/
for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
{
PageData *pageData = &state->pages[i];
Expand All @@ -354,41 +358,34 @@ GenericXLogFinish(GenericXLogState *state)
page = BufferGetPage(pageData->buffer);
pageHeader = (PageHeader) pageData->image;

/*
* Compute delta while we still have both the unmodified page and
* the new image. Not needed if we are logging the full image.
*/
if (!(pageData->flags & GENERIC_XLOG_FULL_IMAGE))
computeDelta(pageData, page, (Page) pageData->image);

/*
* Apply the image, being careful to zero the "hole" between
* pd_lower and pd_upper in order to avoid divergence between
* actual page state and what replay would produce.
*/
memcpy(page, pageData->image, pageHeader->pd_lower);
memset(page + pageHeader->pd_lower, 0,
pageHeader->pd_upper - pageHeader->pd_lower);
memcpy(page + pageHeader->pd_upper,
pageData->image + pageHeader->pd_upper,
BLCKSZ - pageHeader->pd_upper);

MarkBufferDirty(pageData->buffer);

if (pageData->flags & GENERIC_XLOG_FULL_IMAGE)
{
/*
* A full-page image does not require us to supply any xlog
* data. Just apply the image, being careful to zero the
* "hole" between pd_lower and pd_upper in order to avoid
* divergence between actual page state and what replay would
* produce.
*/
memcpy(page, pageData->image, pageHeader->pd_lower);
memset(page + pageHeader->pd_lower, 0,
pageHeader->pd_upper - pageHeader->pd_lower);
memcpy(page + pageHeader->pd_upper,
pageData->image + pageHeader->pd_upper,
BLCKSZ - pageHeader->pd_upper);

XLogRegisterBuffer(i, pageData->buffer,
REGBUF_FORCE_IMAGE | REGBUF_STANDARD);
}
else
{
/*
* In normal mode, calculate delta and write it as xlog data
* associated with this page.
*/
computeDelta(pageData, page, (Page) pageData->image);

/* Apply the image, with zeroed "hole" as above */
memcpy(page, pageData->image, pageHeader->pd_lower);
memset(page + pageHeader->pd_lower, 0,
pageHeader->pd_upper - pageHeader->pd_lower);
memcpy(page + pageHeader->pd_upper,
pageData->image + pageHeader->pd_upper,
BLCKSZ - pageHeader->pd_upper);

XLogRegisterBuffer(i, pageData->buffer, REGBUF_STANDARD);
XLogRegisterBufData(i, pageData->delta, pageData->deltaLen);
}
Expand All @@ -397,15 +394,14 @@ GenericXLogFinish(GenericXLogState *state)
/* Insert xlog record */
lsn = XLogInsert(RM_GENERIC_ID, 0);

/* Set LSN and mark buffers dirty */
/* Set LSN */
for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
{
PageData *pageData = &state->pages[i];

if (BufferIsInvalid(pageData->buffer))
continue;
PageSetLSN(BufferGetPage(pageData->buffer), lsn);
MarkBufferDirty(pageData->buffer);
}
END_CRIT_SECTION();
}
Expand Down

0 comments on commit 04f0baa

Please sign in to comment.