Skip to content

Commit 04f0baa

Browse files
committed
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
1 parent 694d670 commit 04f0baa

File tree

1 file changed

+26
-30
lines changed

1 file changed

+26
-30
lines changed

src/backend/access/transam/generic_xlog.c

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ GenericXLogFinish(GenericXLogState *state)
342342

343343
START_CRIT_SECTION();
344344

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

361+
/*
362+
* Compute delta while we still have both the unmodified page and
363+
* the new image. Not needed if we are logging the full image.
364+
*/
365+
if (!(pageData->flags & GENERIC_XLOG_FULL_IMAGE))
366+
computeDelta(pageData, page, (Page) pageData->image);
367+
368+
/*
369+
* Apply the image, being careful to zero the "hole" between
370+
* pd_lower and pd_upper in order to avoid divergence between
371+
* actual page state and what replay would produce.
372+
*/
373+
memcpy(page, pageData->image, pageHeader->pd_lower);
374+
memset(page + pageHeader->pd_lower, 0,
375+
pageHeader->pd_upper - pageHeader->pd_lower);
376+
memcpy(page + pageHeader->pd_upper,
377+
pageData->image + pageHeader->pd_upper,
378+
BLCKSZ - pageHeader->pd_upper);
379+
380+
MarkBufferDirty(pageData->buffer);
381+
357382
if (pageData->flags & GENERIC_XLOG_FULL_IMAGE)
358383
{
359-
/*
360-
* A full-page image does not require us to supply any xlog
361-
* data. Just apply the image, being careful to zero the
362-
* "hole" between pd_lower and pd_upper in order to avoid
363-
* divergence between actual page state and what replay would
364-
* produce.
365-
*/
366-
memcpy(page, pageData->image, pageHeader->pd_lower);
367-
memset(page + pageHeader->pd_lower, 0,
368-
pageHeader->pd_upper - pageHeader->pd_lower);
369-
memcpy(page + pageHeader->pd_upper,
370-
pageData->image + pageHeader->pd_upper,
371-
BLCKSZ - pageHeader->pd_upper);
372-
373384
XLogRegisterBuffer(i, pageData->buffer,
374385
REGBUF_FORCE_IMAGE | REGBUF_STANDARD);
375386
}
376387
else
377388
{
378-
/*
379-
* In normal mode, calculate delta and write it as xlog data
380-
* associated with this page.
381-
*/
382-
computeDelta(pageData, page, (Page) pageData->image);
383-
384-
/* Apply the image, with zeroed "hole" as above */
385-
memcpy(page, pageData->image, pageHeader->pd_lower);
386-
memset(page + pageHeader->pd_lower, 0,
387-
pageHeader->pd_upper - pageHeader->pd_lower);
388-
memcpy(page + pageHeader->pd_upper,
389-
pageData->image + pageHeader->pd_upper,
390-
BLCKSZ - pageHeader->pd_upper);
391-
392389
XLogRegisterBuffer(i, pageData->buffer, REGBUF_STANDARD);
393390
XLogRegisterBufData(i, pageData->delta, pageData->deltaLen);
394391
}
@@ -397,15 +394,14 @@ GenericXLogFinish(GenericXLogState *state)
397394
/* Insert xlog record */
398395
lsn = XLogInsert(RM_GENERIC_ID, 0);
399396

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

405402
if (BufferIsInvalid(pageData->buffer))
406403
continue;
407404
PageSetLSN(BufferGetPage(pageData->buffer), lsn);
408-
MarkBufferDirty(pageData->buffer);
409405
}
410406
END_CRIT_SECTION();
411407
}

0 commit comments

Comments
 (0)