>From 62e1c6fc679af80f8f4d26f1fe9d2fae8f430100 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 29 May 2013 15:37:05 +0200
Subject: [PATCH] Ensure that all_visible WAL records operate on an intialized
 page

There was a race condition were lazy_scan_heap could cause all_visible records
to be emitted although the page marked all visible wasn't logged in an
initialized state yet causing a PANIC during WAL replay.
---
 src/backend/commands/vacuumlazy.c |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 9d30415..4eff3c1 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -663,6 +663,31 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 			/* empty pages are always all-visible */
 			if (!PageIsAllVisible(page))
 			{
+				/*
+				 * There's a race condition here we need to prevent: Another
+				 * backend might have extended the heap and PageInit'ed but
+				 * ERRORed before filling the page with actual content.
+				 *
+				 * Since relation extension is not WAL logged (and we don't
+				 * even dirty the buffer) it's quite possible that the page's
+				 * content hasn't made it to disk yet, especially on a
+				 * standby. During WAL replay we then could find an
+				 * uninitialized page when trying to set the all visible flag
+				 * which will cause a PANIC lateron.
+				 *
+				 * If there already is a WAL record covering this page
+				 * (i.e. its LSN is valid) the respective record it will
+				 * initialize the page, so we don't need to do anything in that
+				 * case.
+				 *
+				 * XXX: It would be nice to use a logging method supporting
+				 * standard buffers here since log_newpage_buffer() will write
+				 * the full block instead of omitting the hole.
+				 */
+				if (RelationNeedsWAL(onerel) &&
+					PageGetLSN(page) == InvalidXLogRecPtr)
+					log_newpage_buffer(buf);
+
 				PageSetAllVisible(page);
 				MarkBufferDirty(buf);
 				visibilitymap_set(onerel, blkno, buf, InvalidXLogRecPtr,
-- 
1.7.10.4

