From 98dd50a2f70600a799d6d5827d48ddb4fb09fdb7 Mon Sep 17 00:00:00 2001
From: Dilip Kumar <dilip.kumar@enterprisedb.com>
Date: Fri, 13 Mar 2020 14:02:06 +0530
Subject: [PATCH v6 2/4] Extend the assert for the page lock

---
 src/backend/storage/lmgr/lock.c | 41 +++++++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 24ca900..e182ec7 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -171,13 +171,16 @@ typedef struct TwoPhaseLockRecord
 static int	FastPathLocalUseCount = 0;
 
 /*
- * Flag is set if the relation extension lock is currently held by this backend.
- * We need this flag so that we can ensure that while holding the relation
- * extension lock we are not trying to acquire any other heavy weight lock.
- * Basically, that will ensuring that the proc holding relation extension lock
- * can not wait for any another lock which can lead to a deadlock.
+ * Flag is set if the relation extension/page lock is currently held by this
+ * backend.  We need this flag so that we can ensure that while holding the
+ * relation extension/page lock we are not trying to acquire any other heavy
+ * weight lock.  Basically, that will ensuring that the proc holding relation
+ * extension lock can not wait for any another lock which can lead to a
+ * deadlock.  However, for page lock the exception is that while holding the
+ * page lock it can wait on the relation extension lock.
  */
 static bool	IsRelationExtensionLockHeld = false;
+static bool	IsPageLockHeld = false;
 
 /* Macros for manipulating proc->fpLockBits */
 #define FAST_PATH_BITS_PER_SLOT			3
@@ -854,11 +857,17 @@ LockAcquireExtended(const LOCKTAG *locktag,
 
 	/*
 	 * We should not try to acquire any other heavyweight lock if we are already
-	 * holding the relation extension lock.  If we are trying to hold the same
-	 * relation extension lock then it should have been already granted so we
-	 * will not come here.
+	 * holding the relation extension/page lock.  If we are trying to hold the
+	 * same relation extension lock then it should have been already granted so
+	 * we will not come here.  However, While holding the page lock we don't
+	 * need to ensure that whether we are trying to acquire the relation
+	 * extension lock on the same relation or any other relation because we are
+	 * already ensuring that after holding the relation extension lock we are
+	 * not going to wait for any other lock.
 	 */
-	Assert(!IsRelationExtensionLockHeld);
+	Assert(!IsRelationExtensionLockHeld &&
+			(!IsPageLockHeld ||
+			(locktag->locktag_type == LOCKTAG_RELATION_EXTEND)));
 
 	/*
 	 * Prepare to emit a WAL record if acquisition of this lock needs to be
@@ -1308,25 +1317,29 @@ SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
 }
 
 /*
- * CheckAndSetLockHeld -- check and set the flag that we hold relation extension
- *						  lock.
+ * CheckAndSetLockHeld -- check and set the flag that we hold relation
+ *						  extension/page lock.
  */
 static inline void
 CheckAndSetLockHeld(LOCALLOCK *locallock)
 {
 	if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_RELATION_EXTEND)
 		IsRelationExtensionLockHeld = true;
+	else if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_PAGE)
+		IsPageLockHeld = true;
 }
 
 /*
  * CheckAndReSetLockHeld -- check and reset the flag if we have released the
- *							relation extension lock.
+ *							relation extension/page lock.
  */
 static inline void
 CheckAndReSetLockHeld(LOCALLOCK *locallock)
 {
 	if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_RELATION_EXTEND)
 		IsRelationExtensionLockHeld = false;
+	else if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_PAGE)
+		IsPageLockHeld = false;
 }
 
 /*
@@ -1365,7 +1378,7 @@ RemoveLocalLock(LOCALLOCK *locallock)
 					 HASH_REMOVE, NULL))
 		elog(WARNING, "locallock table corrupted");
 
-	/* Check and reset the lock held flag. */
+	/* Check and reset the lock held flags. */
 	CheckAndReSetLockHeld(locallock);
 }
 
@@ -1664,7 +1677,7 @@ GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
 	if (owner != NULL)
 		ResourceOwnerRememberLock(owner, locallock);
 
-	/* Set the flag if we have acquired relation extension lock. */
+	/* Check and set the lock held flags. */
 	CheckAndSetLockHeld(locallock);
 }
 
-- 
1.8.3.1

