diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 5880054245..b1bcb477c6 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -49,6 +49,7 @@
 #include "storage/proc.h"
 #include "storage/smgr.h"
 #include "storage/standby.h"
+#include "utils/ps_status.h"
 #include "utils/rel.h"
 #include "utils/resowner_private.h"
 #include "utils/timestamp.h"
@@ -3669,6 +3670,8 @@ void
 LockBufferForCleanup(Buffer buffer)
 {
 	BufferDesc *bufHdr;
+	TimestampTz waitStart = 0;
+	char		*new_status = NULL;
 
 	Assert(BufferIsValid(buffer));
 	Assert(PinCountWaitBuf == NULL);
@@ -3690,6 +3693,9 @@ LockBufferForCleanup(Buffer buffer)
 
 	bufHdr = GetBufferDescriptor(buffer - 1);
 
+	if (update_process_title)
+		waitStart = GetCurrentTimestamp();
+
 	for (;;)
 	{
 		uint32		buf_state;
@@ -3703,6 +3709,13 @@ LockBufferForCleanup(Buffer buffer)
 		{
 			/* Successfully acquired exclusive lock with pincount 1 */
 			UnlockBufHdr(bufHdr, buf_state);
+
+			/* Reset ps display if we changed it */
+			if (new_status)
+			{
+				set_ps_display(new_status);
+				pfree(new_status);
+			}
 			return;
 		}
 		/* Failed, so mark myself as waiting for pincount 1 */
@@ -3718,6 +3731,22 @@ LockBufferForCleanup(Buffer buffer)
 		UnlockBufHdr(bufHdr, buf_state);
 		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
+		/* Report via ps if we have been waiting for more than 500 msec */
+		if (update_process_title && new_status == NULL &&
+			TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(),
+									   500))
+		{
+			const char *old_status;
+			int			len;
+
+			old_status = get_ps_display(&len);
+			new_status = (char *) palloc(len + 8 + 1);
+			memcpy(new_status, old_status, len);
+			strcpy(new_status + len, " waiting");
+			set_ps_display(new_status);
+			new_status[len] = '\0'; /* truncate off " waiting" */
+		}
+
 		/* Wait to be signaled by UnpinBuffer() */
 		if (InHotStandby)
 		{
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 08f695a980..24fc6de521 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -47,6 +47,7 @@ static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlis
 static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason);
 static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts);
 static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks);
+static char *update_process_title_waiting(TimestampTz waitStart);
 
 /*
  * Keep track of all the locks owned by a given transaction.
@@ -244,24 +245,9 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
 		/* wait until the virtual xid is gone */
 		while (!VirtualXactLock(*waitlist, false))
 		{
-			/*
-			 * Report via ps if we have been waiting for more than 500 msec
-			 * (should that be configurable?)
-			 */
-			if (update_process_title && new_status == NULL && report_waiting &&
-				TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(),
-										   500))
-			{
-				const char *old_status;
-				int			len;
-
-				old_status = get_ps_display(&len);
-				new_status = (char *) palloc(len + 8 + 1);
-				memcpy(new_status, old_status, len);
-				strcpy(new_status + len, " waiting");
-				set_ps_display(new_status);
-				new_status[len] = '\0'; /* truncate off " waiting" */
-			}
+			/* Report via ps we are waiting */
+			if (update_process_title && new_status == NULL && report_waiting)
+				new_status = update_process_title_waiting(waitStart);
 
 			/* Is it time to kill it? */
 			if (WaitExceedsMaxStandbyDelay())
@@ -352,6 +338,12 @@ ResolveRecoveryConflictWithTablespace(Oid tsid)
 void
 ResolveRecoveryConflictWithDatabase(Oid dbid)
 {
+	char		*new_status = NULL;
+	TimestampTz waitStart = 0;
+
+	if (update_process_title)
+		waitStart = GetCurrentTimestamp();
+
 	/*
 	 * We don't do ResolveRecoveryConflictWithVirtualXIDs() here since that
 	 * only waits for transactions and completely idle sessions would block
@@ -365,6 +357,10 @@ ResolveRecoveryConflictWithDatabase(Oid dbid)
 	 */
 	while (CountDBBackends(dbid) > 0)
 	{
+		/* Report via ps we are waiting */
+		if (update_process_title && new_status == NULL)
+			new_status = update_process_title_waiting(waitStart);
+
 		CancelDBBackends(dbid, PROCSIG_RECOVERY_CONFLICT_DATABASE, true);
 
 		/*
@@ -373,6 +369,13 @@ ResolveRecoveryConflictWithDatabase(Oid dbid)
 		 */
 		pg_usleep(10000);
 	}
+
+	/* Reset ps display if we changed it */
+	if (new_status)
+	{
+		set_ps_display(new_status);
+		pfree(new_status);
+	}
 }
 
 /*
@@ -1108,3 +1111,33 @@ LogStandbyInvalidations(int nmsgs, SharedInvalidationMessage *msgs,
 					 nmsgs * sizeof(SharedInvalidationMessage));
 	XLogInsert(RM_STANDBY_ID, XLOG_INVALIDATIONS);
 }
+
+/*
+ * Append " waiting" to the process title if we have been waiting for
+ * more than 500 msec since waitStart, and return palloc'd original
+ * process title. (should that be configurable?)
+ */
+static char *
+update_process_title_waiting(TimestampTz waitStart)
+{
+	char	   *new_status = NULL;
+
+	if (!update_process_title)
+		return NULL;
+
+	if (TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(),
+								   500))
+	{
+		const char *old_status;
+		int			len;
+
+		old_status = get_ps_display(&len);
+		new_status = (char *) palloc(len + 8 + 1);
+		memcpy(new_status, old_status, len);
+		strcpy(new_status + len, " waiting");
+		set_ps_display(new_status);
+		new_status[len] = '\0'; /* truncate off " waiting" */
+	}
+
+	return new_status;
+}
