From b8fd1a09f382f04c41128fded4d56da2127ce92d Mon Sep 17 00:00:00 2001
From: Jeff Davis <jdavis@postgresql.org>
Date: Mon, 17 Jun 2013 08:02:12 -0700
Subject: [PATCH] Add buffer_std flag to MarkBufferDirtyHint().

MarkBufferDirtyHint() writes WAL, and should know if it's got a
standard buffer or not. Currently, the only callers where buffer_std
is false are related to the FSM.

In passing, rename XLOG_HINT to XLOG_FPI, which is more descriptive.

Back-patch to 9.3.
---
 src/backend/access/hash/hash.c            |  2 +-
 src/backend/access/heap/pruneheap.c       |  2 +-
 src/backend/access/nbtree/nbtinsert.c     |  4 ++--
 src/backend/access/nbtree/nbtree.c        |  2 +-
 src/backend/access/nbtree/nbtutils.c      |  2 +-
 src/backend/access/rmgrdesc/xlogdesc.c    |  4 ++--
 src/backend/access/transam/xlog.c         | 18 +++++++++---------
 src/backend/commands/sequence.c           |  2 +-
 src/backend/storage/buffer/bufmgr.c       |  4 ++--
 src/backend/storage/freespace/freespace.c |  8 ++++----
 src/backend/storage/freespace/fsmpage.c   |  2 +-
 src/backend/utils/time/tqual.c            |  2 +-
 src/include/access/xlog.h                 |  2 +-
 src/include/catalog/pg_control.h          |  2 +-
 src/include/storage/bufmgr.h              |  2 +-
 15 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 5ca27a231e2..8895f585034 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -287,7 +287,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 			/*
 			 * Since this can be redone later if needed, mark as a hint.
 			 */
-			MarkBufferDirtyHint(buf);
+			MarkBufferDirtyHint(buf, true);
 		}
 
 		/*
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 2ab723ddf19..c6e31542935 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -262,7 +262,7 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin,
 		{
 			((PageHeader) page)->pd_prune_xid = prstate.new_prune_xid;
 			PageClearFull(page);
-			MarkBufferDirtyHint(buffer);
+			MarkBufferDirtyHint(buffer, true);
 		}
 	}
 
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 6ad4f765f5b..a452fea8410 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -413,9 +413,9 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
 					 * crucial. Be sure to mark the proper buffer dirty.
 					 */
 					if (nbuf != InvalidBuffer)
-						MarkBufferDirtyHint(nbuf);
+						MarkBufferDirtyHint(nbuf, true);
 					else
-						MarkBufferDirtyHint(buf);
+						MarkBufferDirtyHint(buf, true);
 				}
 			}
 		}
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 621b0556390..073190ffd53 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -1052,7 +1052,7 @@ restart:
 				opaque->btpo_cycleid == vstate->cycleid)
 			{
 				opaque->btpo_cycleid = 0;
-				MarkBufferDirtyHint(buf);
+				MarkBufferDirtyHint(buf, true);
 			}
 		}
 
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index fe53ec1fe0a..352c77cbea2 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -1789,7 +1789,7 @@ _bt_killitems(IndexScanDesc scan, bool haveLock)
 	if (killedsomething)
 	{
 		opaque->btpo_flags |= BTP_HAS_GARBAGE;
-		MarkBufferDirtyHint(so->currPos.buf);
+		MarkBufferDirtyHint(so->currPos.buf, true);
 	}
 
 	if (!haveLock)
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 2bad52748a3..12370521d45 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -82,11 +82,11 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
 		appendStringInfo(buf, "restore point: %s", xlrec->rp_name);
 
 	}
-	else if (info == XLOG_HINT)
+	else if (info == XLOG_FPI)
 	{
 		BkpBlock   *bkp = (BkpBlock *) rec;
 
-		appendStringInfo(buf, "page hint: %s block %u",
+		appendStringInfo(buf, "full-page image: %s block %u",
 						 relpathperm(bkp->node, bkp->fork),
 						 bkp->block);
 	}
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 654c9c18d8b..9f858995d12 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7681,12 +7681,9 @@ XLogRestorePoint(const char *rpName)
  * records. In that case, multiple copies of the same block would be recorded
  * in separate WAL records by different backends, though that is still OK from
  * a correctness perspective.
- *
- * Note that this only works for buffers that fit the standard page model,
- * i.e. those for which buffer_std == true
  */
 XLogRecPtr
-XLogSaveBufferForHint(Buffer buffer)
+XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
 {
 	XLogRecPtr	recptr = InvalidXLogRecPtr;
 	XLogRecPtr	lsn;
@@ -7708,7 +7705,7 @@ XLogSaveBufferForHint(Buffer buffer)
 	 * and reset rdata for any actual WAL record insert.
 	 */
 	rdata[0].buffer = buffer;
-	rdata[0].buffer_std = true;
+	rdata[0].buffer_std = buffer_std;
 
 	/*
 	 * Check buffer while not holding an exclusive lock.
@@ -7722,6 +7719,9 @@ XLogSaveBufferForHint(Buffer buffer)
 		 * Copy buffer so we don't have to worry about concurrent hint bit or
 		 * lsn updates. We assume pd_lower/upper cannot be changed without an
 		 * exclusive lock, so the contents bkp are not racy.
+		 *
+		 * With buffer_std set to false, XLogCheckBuffer() sets hole_length and
+		 * hole_offset to 0; so the following code is safe for either case.
 		 */
 		memcpy(copied_buffer, origdata, bkpb.hole_offset);
 		memcpy(copied_buffer + bkpb.hole_offset,
@@ -7744,7 +7744,7 @@ XLogSaveBufferForHint(Buffer buffer)
 		rdata[1].buffer = InvalidBuffer;
 		rdata[1].next = NULL;
 
-		recptr = XLogInsert(RM_XLOG_ID, XLOG_HINT, rdata);
+		recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI, rdata);
 	}
 
 	return recptr;
@@ -8109,14 +8109,14 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
 	{
 		/* nothing to do here */
 	}
-	else if (info == XLOG_HINT)
+	else if (info == XLOG_FPI)
 	{
 		char	   *data;
 		BkpBlock	bkpb;
 
 		/*
-		 * Hint bit records contain a backup block stored "inline" in the
-		 * normal data since the locking when writing hint records isn't
+		 * Full-page image (FPI) records contain a backup block stored "inline"
+		 * in the normal data since the locking when writing hint records isn't
 		 * sufficient to use the normal backup block mechanism, which assumes
 		 * exclusive lock on the buffer supplied.
 		 *
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index bffc12ed0e9..ddfaf3bd293 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1118,7 +1118,7 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
 		HeapTupleHeaderSetXmax(seqtuple->t_data, InvalidTransactionId);
 		seqtuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
 		seqtuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
-		MarkBufferDirtyHint(*buf);
+		MarkBufferDirtyHint(*buf, true);
 	}
 
 	seq = (Form_pg_sequence) GETSTRUCT(seqtuple);
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index c6b033cf417..8079226864d 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2587,7 +2587,7 @@ IncrBufferRefCount(Buffer buffer)
  *	  (due to a race condition), so it cannot be used for important changes.
  */
 void
-MarkBufferDirtyHint(Buffer buffer)
+MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
 {
 	volatile BufferDesc *bufHdr;
 	Page		page = BufferGetPage(buffer);
@@ -2671,7 +2671,7 @@ MarkBufferDirtyHint(Buffer buffer)
 			 * rather than full transactionids.
 			 */
 			MyPgXact->delayChkpt = delayChkpt = true;
-			lsn = XLogSaveBufferForHint(buffer);
+			lsn = XLogSaveBufferForHint(buffer, buffer_std);
 		}
 
 		LockBufHdr(bufHdr);
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index b76bf9be6b4..b15cf8fe452 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -216,7 +216,7 @@ XLogRecordPageWithFreeSpace(RelFileNode rnode, BlockNumber heapBlk,
 		PageInit(page, BLCKSZ, 0);
 
 	if (fsm_set_avail(page, slot, new_cat))
-		MarkBufferDirtyHint(buf);
+		MarkBufferDirtyHint(buf, false);
 	UnlockReleaseBuffer(buf);
 }
 
@@ -286,7 +286,7 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
 			return;				/* nothing to do; the FSM was already smaller */
 		LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
 		fsm_truncate_avail(BufferGetPage(buf), first_removed_slot);
-		MarkBufferDirtyHint(buf);
+		MarkBufferDirtyHint(buf, false);
 		UnlockReleaseBuffer(buf);
 
 		new_nfsmblocks = fsm_logical_to_physical(first_removed_address) + 1;
@@ -619,7 +619,7 @@ fsm_set_and_search(Relation rel, FSMAddress addr, uint16 slot,
 	page = BufferGetPage(buf);
 
 	if (fsm_set_avail(page, slot, newValue))
-		MarkBufferDirtyHint(buf);
+		MarkBufferDirtyHint(buf, false);
 
 	if (minValue != 0)
 	{
@@ -770,7 +770,7 @@ fsm_vacuum_page(Relation rel, FSMAddress addr, bool *eof_p)
 			{
 				LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
 				fsm_set_avail(BufferGetPage(buf), slot, child_avail);
-				MarkBufferDirtyHint(buf);
+				MarkBufferDirtyHint(buf, false);
 				LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 			}
 		}
diff --git a/src/backend/storage/freespace/fsmpage.c b/src/backend/storage/freespace/fsmpage.c
index 19c8e09148b..8376a7fc0f8 100644
--- a/src/backend/storage/freespace/fsmpage.c
+++ b/src/backend/storage/freespace/fsmpage.c
@@ -284,7 +284,7 @@ restart:
 				exclusive_lock_held = true;
 			}
 			fsm_rebuild_page(page);
-			MarkBufferDirtyHint(buf);
+			MarkBufferDirtyHint(buf, false);
 			goto restart;
 		}
 	}
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index ab4020a710b..55563ea335d 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -121,7 +121,7 @@ SetHintBits(HeapTupleHeader tuple, Buffer buffer,
 	}
 
 	tuple->t_infomask |= infomask;
-	MarkBufferDirtyHint(buffer);
+	MarkBufferDirtyHint(buffer, true);
 }
 
 /*
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index b4a75cee220..83e583259dd 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -267,7 +267,7 @@ extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
 extern int	XLogFileInit(XLogSegNo segno, bool *use_existent, bool use_lock);
 extern int	XLogFileOpen(XLogSegNo segno);
 
-extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer);
+extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
 extern void XLogSetAsyncXactLSN(XLogRecPtr record);
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 4f154a95892..0e297610d8a 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -67,7 +67,7 @@ typedef struct CheckPoint
 #define XLOG_RESTORE_POINT				0x70
 #define XLOG_FPW_CHANGE					0x80
 #define XLOG_END_OF_RECOVERY			0x90
-#define XLOG_HINT						0xA0
+#define XLOG_FPI						0xA0
 
 
 /*
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 9be18608426..6dc031ead54 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -204,7 +204,7 @@ extern Size BufferShmemSize(void);
 extern void BufferGetTag(Buffer buffer, RelFileNode *rnode,
 			 ForkNumber *forknum, BlockNumber *blknum);
 
-extern void MarkBufferDirtyHint(Buffer buffer);
+extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);
 
 extern void UnlockBuffers(void);
 extern void LockBuffer(Buffer buffer, int mode);
-- 
GitLab