aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Kapila <akapila@postgresql.org>2020-03-19 08:11:45 +0530
committerAmit Kapila <akapila@postgresql.org>2020-03-19 08:11:45 +0530
commit72e78d831ab5550c39f2dcc7cc5d44c406ec3dc2 (patch)
tree78d8528b569a834c79478d8d3acf4f20aaeb1913
parent6312c08a291fc34068571ec64ee439f2674d739a (diff)
downloadpostgresql-72e78d831ab5550c39f2dcc7cc5d44c406ec3dc2.tar.gz
postgresql-72e78d831ab5550c39f2dcc7cc5d44c406ec3dc2.zip
Add assert to ensure that page locks don't participate in deadlock cycle.
Assert that we don't acquire any other heavyweight lock while holding the page lock except for relation extension. However, these locks are never taken in reverse order which implies that page locks will never participate in the deadlock cycle. Similar to relation extension, page locks are also held for a short duration, so imposing such a restriction won't hurt. Author: Dilip Kumar, with few changes by Amit Kapila Reviewed-by: Amit Kapila, Kuntal Ghosh and Sawada Masahiko Discussion: https://postgr.es/m/CAD21AoCmT3cFQUN4aVvzy5chw7DuzXrJCbrjTU05B+Ss=Gn1LA@mail.gmail.com
-rw-r--r--src/backend/storage/lmgr/lock.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 9f55132724f..be44913e2a0 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -185,6 +185,18 @@ static int FastPathLocalUseCount = 0;
*/
static bool IsRelationExtensionLockHeld PG_USED_FOR_ASSERTS_ONLY = false;
+/*
+ * Flag to indicate if the page lock is held by this backend. We don't
+ * acquire any other heavyweight lock while holding the page lock except for
+ * relation extension. However, these locks are never taken in reverse order
+ * which implies that page locks will also never participate in the deadlock
+ * cycle.
+ *
+ * Similar to relation extension, page locks are also held for a short
+ * duration, so imposing such a restriction won't hurt.
+ */
+static bool IsPageLockHeld PG_USED_FOR_ASSERTS_ONLY = false;
+
/* Macros for manipulating proc->fpLockBits */
#define FAST_PATH_BITS_PER_SLOT 3
#define FAST_PATH_LOCKNUMBER_OFFSET 1
@@ -863,6 +875,13 @@ LockAcquireExtended(const LOCKTAG *locktag,
Assert(!IsRelationExtensionLockHeld);
/*
+ * We don't acquire any other heavyweight lock while holding the page lock
+ * except for relation extension.
+ */
+ Assert(!IsPageLockHeld ||
+ (locktag->locktag_type == LOCKTAG_RELATION_EXTEND));
+
+ /*
* Prepare to emit a WAL record if acquisition of this lock needs to be
* replayed in a standby server.
*
@@ -1310,10 +1329,10 @@ SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
}
/*
- * Check and set/reset the flag that we hold the relation extension lock.
+ * Check and set/reset the flag that we hold the relation extension/page lock.
*
* It is callers responsibility that this function is called after
- * acquiring/releasing the relation extension lock.
+ * acquiring/releasing the relation extension/page lock.
*
* Pass acquired as true if lock is acquired, false otherwise.
*/
@@ -1323,6 +1342,9 @@ CheckAndSetLockHeld(LOCALLOCK *locallock, bool acquired)
#ifdef USE_ASSERT_CHECKING
if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_RELATION_EXTEND)
IsRelationExtensionLockHeld = acquired;
+ else if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_PAGE)
+ IsPageLockHeld = acquired;
+
#endif
}