aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorAmit Kapila <akapila@postgresql.org>2018-09-13 15:30:26 +0530
committerAmit Kapila <akapila@postgresql.org>2018-09-13 15:32:50 +0530
commitbc153c941d2ec4e605b1e79be9478abc3d166a18 (patch)
treecf1ddc9e9f0770d1838e2fb8cd558379b87e9022 /src/backend/access/transam/xlog.c
parent514a731ddcd8449d8a7bfb96f138c72c694a7ef8 (diff)
downloadpostgresql-bc153c941d2ec4e605b1e79be9478abc3d166a18.tar.gz
postgresql-bc153c941d2ec4e605b1e79be9478abc3d166a18.zip
Attach FPI to the first record after full_page_writes is turned on.
XLogInsert fails to attach a required FPI to the first record after full_page_writes is turned on by the last checkpoint. This bug got introduced in 9.5 due to code rearrangement in commits 2c03216d83 and 2076db2aea. Fix it by ensuring that XLogInsertRecord performs a recomputation when the given record is generated with FPW as off but found that the flag has been turned on while actually inserting the record. Reported-by: Kyotaro Horiguchi Author: Kyotaro Horiguchi Reviewed-by: Amit Kapila Backpatch-through: 9.5 where this problem was introduced Discussion: https://postgr.es/m/20180420.151043.74298611.horiguchi.kyotaro@lab.ntt.co.jp
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 85a7b285ec3..3025d0badb8 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -944,7 +944,7 @@ static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
*
* If 'fpw_lsn' is valid, it is the oldest LSN among the pages that this
* WAL record applies to, that were not included in the record as full page
- * images. If fpw_lsn >= RedoRecPtr, the function does not perform the
+ * images. If fpw_lsn <= RedoRecPtr, the function does not perform the
* insertion and returns InvalidXLogRecPtr. The caller can then recalculate
* which pages need a full-page image, and retry. If fpw_lsn is invalid, the
* record is always inserted.
@@ -977,6 +977,7 @@ XLogInsertRecord(XLogRecData *rdata,
info == XLOG_SWITCH);
XLogRecPtr StartPos;
XLogRecPtr EndPos;
+ bool prevDoPageWrites = doPageWrites;
/* we assume that all of the record header is in the first chunk */
Assert(rdata->len >= SizeOfXLogRecord);
@@ -1024,10 +1025,14 @@ XLogInsertRecord(XLogRecData *rdata,
WALInsertLockAcquire();
/*
- * Check to see if my copy of RedoRecPtr or doPageWrites is out of date.
- * If so, may have to go back and have the caller recompute everything.
- * This can only happen just after a checkpoint, so it's better to be slow
- * in this case and fast otherwise.
+ * Check to see if my copy of RedoRecPtr is out of date. If so, may have
+ * to go back and have the caller recompute everything. This can only
+ * happen just after a checkpoint, so it's better to be slow in this case
+ * and fast otherwise.
+ *
+ * Also check to see if fullPageWrites or forcePageWrites was just turned
+ * on; if we weren't already doing full-page writes then go back and
+ * recompute.
*
* If we aren't doing full-page writes then RedoRecPtr doesn't actually
* affect the contents of the XLOG record, so we'll update our local copy
@@ -1042,7 +1047,9 @@ XLogInsertRecord(XLogRecData *rdata,
}
doPageWrites = (Insert->fullPageWrites || Insert->forcePageWrites);
- if (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr && doPageWrites)
+ if (doPageWrites &&
+ (!prevDoPageWrites ||
+ (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr)))
{
/*
* Oops, some buffer now needs to be backed up that the caller didn't