From 40bdbe409fec1c6c2832b070c3b961f28a0e4e83 Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Thu, 23 Apr 2020 14:43:54 -0700
Subject: [PATCH 3/6] Mark lockless nbtree leaf page memory undefined.

---
 src/backend/access/nbtree/nbtsearch.c | 34 +++++++++++++++++++++++++++
 src/backend/access/nbtree/nbtutils.c  | 12 ++++++++++
 2 files changed, 46 insertions(+)

diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 8ff49ce6d6..96e99774ba 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -21,6 +21,7 @@
 #include "pgstat.h"
 #include "storage/predicate.h"
 #include "utils/lsyscache.h"
+#include "utils/memdebug.h"
 #include "utils/rel.h"
 
 
@@ -66,6 +67,12 @@ _bt_drop_lock_and_maybe_pin(IndexScanDesc scan, BTScanPos sp)
 {
 	LockBuffer(sp->buf, BUFFER_LOCK_UNLOCK);
 
+	/*
+	 * Buffer is pinned, and so is expected to be defined and addressable when
+	 * we're called, no matter what happens here
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(sp->buf), BLCKSZ);
+
 	if (IsMVCCSnapshot(scan->xs_snapshot) &&
 		RelationNeedsWAL(scan->indexRelation) &&
 		!scan->xs_want_itup)
@@ -73,6 +80,12 @@ _bt_drop_lock_and_maybe_pin(IndexScanDesc scan, BTScanPos sp)
 		ReleaseBuffer(sp->buf);
 		sp->buf = InvalidBuffer;
 	}
+#ifdef USE_VALGRIND
+	else if (!RelationUsesLocalBuffers(scan->indexRelation))
+	{
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(sp->buf), BLCKSZ);
+	}
+#endif
 }
 
 /*
@@ -2065,7 +2078,28 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir)
 		 * deleted.
 		 */
 		if (BTScanPosIsPinned(so->currPos))
+		{
+#ifdef USE_VALGRIND
+			if (!RelationUsesLocalBuffers(scan->indexRelation))
+			{
+				Page		page;
+
+				/*
+				 * Must not have called _bt_killitems() from _bt_steppage()
+				 * (our caller), so mark buffer's page defined here instead.
+				 *
+				 * (If we happened to have killed items then _bt_killitems()
+				 * would have been called and would have dropped both the lock
+				 * and the pin, so we'd have both marked the buffer's page as
+				 * defined before starting to kill, and released the buffer
+				 * entirely once we were done with killing.)
+				 */
+				page = BufferGetPage(so->currPos.buf);
+				VALGRIND_MAKE_MEM_DEFINED(page, BLCKSZ);
+			}
+#endif
 			LockBuffer(so->currPos.buf, BT_READ);
+		}
 		else
 			so->currPos.buf = _bt_getbuf(rel, so->currPos.currPage, BT_READ);
 
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index ce48a51640..05fcc3b873 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -27,6 +27,7 @@
 #include "utils/array.h"
 #include "utils/datum.h"
 #include "utils/lsyscache.h"
+#include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
 
@@ -1747,6 +1748,17 @@ _bt_killitems(IndexScanDesc scan)
 		LockBuffer(so->currPos.buf, BT_READ);
 
 		page = BufferGetPage(so->currPos.buf);
+
+#ifdef USE_VALGRIND
+		if (!RelationUsesLocalBuffers(scan->indexRelation))
+		{
+			/*
+			 * We had a pin but not a buffer lock, so must mark page memory
+			 * defined once again
+			 */
+			VALGRIND_MAKE_MEM_DEFINED(page, BLCKSZ);
+		}
+#endif
 	}
 	else
 	{
-- 
2.25.1

