*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 79,84 **** bool		XLogArchiveMode = false;
--- 79,85 ----
  char	   *XLogArchiveCommand = NULL;
  bool		EnableHotStandby = false;
  bool		fullPageWrites = true;
+ bool		walLogHintbits = false;
  bool		log_checkpoints = false;
  int			sync_method = DEFAULT_SYNC_METHOD;
  int			wal_level = WAL_LEVEL_MINIMAL;
***************
*** 5265,5270 **** BootStrapXLOG(void)
--- 5266,5272 ----
  	ControlFile->max_locks_per_xact = max_locks_per_xact;
  	ControlFile->wal_level = wal_level;
  	ControlFile->data_checksum_version = bootstrap_data_checksum_version;
+ 	ControlFile->wal_log_hintbits = walLogHintbits;
  
  	/* some additional ControlFile fields are set in WriteControlFile() */
  
***************
*** 8921,8926 **** static void
--- 8923,8929 ----
  XLogReportParameters(void)
  {
  	if (wal_level != ControlFile->wal_level ||
+ 		walLogHintbits != ControlFile->wal_log_hintbits ||
  		MaxConnections != ControlFile->MaxConnections ||
  		max_worker_processes != ControlFile->max_worker_processes ||
  		max_prepared_xacts != ControlFile->max_prepared_xacts ||
***************
*** 8943,8948 **** XLogReportParameters(void)
--- 8946,8952 ----
  			xlrec.max_prepared_xacts = max_prepared_xacts;
  			xlrec.max_locks_per_xact = max_locks_per_xact;
  			xlrec.wal_level = wal_level;
+ 			xlrec.wal_log_hintbits = walLogHintbits;
  
  			rdata.buffer = InvalidBuffer;
  			rdata.data = (char *) &xlrec;
***************
*** 8957,8962 **** XLogReportParameters(void)
--- 8961,8967 ----
  		ControlFile->max_prepared_xacts = max_prepared_xacts;
  		ControlFile->max_locks_per_xact = max_locks_per_xact;
  		ControlFile->wal_level = wal_level;
+ 		ControlFile->wal_log_hintbits = walLogHintbits;
  		UpdateControlFile();
  	}
  }
***************
*** 9343,9348 **** xlog_redo(XLogRecPtr lsn, XLogRecord *record)
--- 9348,9354 ----
  		ControlFile->max_prepared_xacts = xlrec.max_prepared_xacts;
  		ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact;
  		ControlFile->wal_level = xlrec.wal_level;
+ 		ControlFile->wal_log_hintbits = walLogHintbits;
  
  		/*
  		 * Update minRecoveryPoint to ensure that if recovery is aborted, we
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
***************
*** 817,822 **** PostmasterMain(int argc, char *argv[])
--- 817,825 ----
  	if (XLogArchiveMode && wal_level == WAL_LEVEL_MINIMAL)
  		ereport(ERROR,
  				(errmsg("WAL archival (archive_mode=on) requires wal_level \"archive\" or \"hot_standby\"")));
+ 	if (walLogHintbits && wal_level == WAL_LEVEL_MINIMAL)
+ 		ereport(ERROR,
+ 				(errmsg("Logging hintbit (wal_log_hintbits = on) requires wal_level \"archive\" or \"hot_standby\"")));
  	if (max_wal_senders > 0 && wal_level == WAL_LEVEL_MINIMAL)
  		ereport(ERROR,
  				(errmsg("WAL streaming (max_wal_senders > 0) requires wal_level \"archive\" or \"hot_standby\"")));
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
***************
*** 2626,2633 **** MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
  		bool		delayChkpt = false;
  
  		/*
! 		 * If checksums are enabled, and the buffer is permanent, then a full
! 		 * page image may be required even for some hint bit updates to
  		 * protect against torn pages. This full page image is only necessary
  		 * if the hint bit update is the first change to the page since the
  		 * last checkpoint.
--- 2626,2633 ----
  		bool		delayChkpt = false;
  
  		/*
! 		 * If checksums or logging hintbit are enabled, and the buffer is permanent,
! 		 * then a full page image may be required even for some hint bit updates to
  		 * protect against torn pages. This full page image is only necessary
  		 * if the hint bit update is the first change to the page since the
  		 * last checkpoint.
***************
*** 2635,2641 **** MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
  		 * We don't check full_page_writes here because that logic is included
  		 * when we call XLogInsert() since the value changes dynamically.
  		 */
! 		if (DataChecksumsEnabled() && (bufHdr->flags & BM_PERMANENT))
  		{
  			/*
  			 * If we're in recovery we cannot dirty a page because of a hint.
--- 2635,2641 ----
  		 * We don't check full_page_writes here because that logic is included
  		 * when we call XLogInsert() since the value changes dynamically.
  		 */
! 		if ((DataChecksumsEnabled() || walLogHintbits) && (bufHdr->flags & BM_PERMANENT))
  		{
  			/*
  			 * If we're in recovery we cannot dirty a page because of a hint.
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 854,859 **** static struct config_bool ConfigureNamesBool[] =
--- 854,870 ----
  		true,
  		NULL, NULL, NULL
  	},
+ 
+ 	{
+ 		{"wal_log_hintbits", PGC_SIGHUP, WAL_SETTINGS,
+ 			gettext_noop("Writes hintbit log to WAL when first updated after a checkpoint"),
+ 			NULL
+ 		},
+ 		&walLogHintbits,
+ 		false,
+ 		NULL, NULL, NULL
+ 	},
+ 
  	{
  		{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
  			gettext_noop("Logs each checkpoint."),
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 181,186 ****
--- 181,187 ----
  					#   fsync_writethrough
  					#   open_sync
  #full_page_writes = on			# recover from partial page writes
+ #wal_log_hintbits = off			# turns logging WAL when updating hintbit
  #wal_buffers = -1			# min 32kB, -1 sets based on shared_buffers
  					# (change requires restart)
  #wal_writer_delay = 200ms		# 1-10000 milliseconds
*** a/src/bin/pg_controldata/pg_controldata.c
--- b/src/bin/pg_controldata/pg_controldata.c
***************
*** 291,295 **** main(int argc, char *argv[])
--- 291,297 ----
  		   (ControlFile.float8ByVal ? _("by value") : _("by reference")));
  	printf(_("Data page checksum version:           %u\n"),
  		   ControlFile.data_checksum_version);
+ 	printf(_("Wal log hintbits:                     %u\n"),
+ 		   ControlFile.wal_log_hintbits);
  	return 0;
  }
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 189,194 **** extern bool XLogArchiveMode;
--- 189,195 ----
  extern char *XLogArchiveCommand;
  extern bool EnableHotStandby;
  extern bool fullPageWrites;
+ extern bool walLogHintbits;
  extern bool log_checkpoints;
  extern int	num_xloginsert_slots;
  
*** a/src/include/access/xlog_internal.h
--- b/src/include/access/xlog_internal.h
***************
*** 209,214 **** typedef struct xl_parameter_change
--- 209,215 ----
  	int			max_prepared_xacts;
  	int			max_locks_per_xact;
  	int			wal_level;
+ 	bool		wal_log_hintbits;
  } xl_parameter_change;
  
  /* logs restore point */
*** a/src/include/catalog/pg_control.h
--- b/src/include/catalog/pg_control.h
***************
*** 219,224 **** typedef struct ControlFileData
--- 219,227 ----
  
  	/* CRC of all above ... MUST BE LAST! */
  	pg_crc32	crc;
+ 
+ 	/* Enable logging WAL when updating hintbit */
+ 	bool		wal_log_hintbits;
  } ControlFileData;
  
  /*
