mirror of
https://github.com/postgres/postgres.git
synced 2025-05-17 06:41:24 +03:00
Fix bug in GenericXLogFinish().
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
This commit is contained in:
parent
b36d78e21a
commit
469d367bee
@ -342,6 +342,10 @@ GenericXLogFinish(GenericXLogState *state)
|
|||||||
|
|
||||||
START_CRIT_SECTION();
|
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++)
|
for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
|
||||||
{
|
{
|
||||||
PageData *pageData = &state->pages[i];
|
PageData *pageData = &state->pages[i];
|
||||||
@ -354,41 +358,34 @@ GenericXLogFinish(GenericXLogState *state)
|
|||||||
page = BufferGetPage(pageData->buffer);
|
page = BufferGetPage(pageData->buffer);
|
||||||
pageHeader = (PageHeader) pageData->image;
|
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)
|
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,
|
XLogRegisterBuffer(i, pageData->buffer,
|
||||||
REGBUF_FORCE_IMAGE | REGBUF_STANDARD);
|
REGBUF_FORCE_IMAGE | REGBUF_STANDARD);
|
||||||
}
|
}
|
||||||
else
|
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);
|
XLogRegisterBuffer(i, pageData->buffer, REGBUF_STANDARD);
|
||||||
XLogRegisterBufData(i, pageData->delta, pageData->deltaLen);
|
XLogRegisterBufData(i, pageData->delta, pageData->deltaLen);
|
||||||
}
|
}
|
||||||
@ -397,7 +394,7 @@ GenericXLogFinish(GenericXLogState *state)
|
|||||||
/* Insert xlog record */
|
/* Insert xlog record */
|
||||||
lsn = XLogInsert(RM_GENERIC_ID, 0);
|
lsn = XLogInsert(RM_GENERIC_ID, 0);
|
||||||
|
|
||||||
/* Set LSN and mark buffers dirty */
|
/* Set LSN */
|
||||||
for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
|
for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
|
||||||
{
|
{
|
||||||
PageData *pageData = &state->pages[i];
|
PageData *pageData = &state->pages[i];
|
||||||
@ -405,7 +402,6 @@ GenericXLogFinish(GenericXLogState *state)
|
|||||||
if (BufferIsInvalid(pageData->buffer))
|
if (BufferIsInvalid(pageData->buffer))
|
||||||
continue;
|
continue;
|
||||||
PageSetLSN(BufferGetPage(pageData->buffer), lsn);
|
PageSetLSN(BufferGetPage(pageData->buffer), lsn);
|
||||||
MarkBufferDirty(pageData->buffer);
|
|
||||||
}
|
}
|
||||||
END_CRIT_SECTION();
|
END_CRIT_SECTION();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user