commit 0b1fbfb34236882591c5ac6665a407d9780f4017
Author: anastasia <a.lubennikova@postgrespro.ru>
Date:   Wed Aug 5 15:56:10 2020 +0300

    fix race in BRIN page locking

diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c
index 7dcb1cd73f..89724c3bd4 100644
--- a/src/backend/access/brin/brin_revmap.c
+++ b/src/backend/access/brin/brin_revmap.c
@@ -207,6 +207,7 @@ brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk,
 	ItemId		lp;
 	BrinTuple  *tup;
 	ItemPointerData previptr;
+	bool in_retry = false;
 
 	/* normalize the heap block number to be the first page in the range */
 	heapBlk = (heapBlk / revmap->rm_pagesPerRange) * revmap->rm_pagesPerRange;
@@ -283,9 +284,23 @@ brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk,
 		if (BRIN_IS_REGULAR_PAGE(page))
 		{
 			if (*off > PageGetMaxOffsetNumber(page))
-				ereport(ERROR,
-						(errcode(ERRCODE_INDEX_CORRUPTED),
-						 errmsg_internal("corrupted BRIN index: inconsistent range map")));
+			{
+				if (in_retry)
+					ereport(ERROR,
+							(errcode(ERRCODE_INDEX_CORRUPTED),
+							errmsg_internal("corrupted BRIN index: inconsistent range map")));
+				else
+				{
+					/*
+					 * Assume that the revmap was updated concurrently.
+					 * Retry only once to avoid eternal looping in case
+					 * the index is really corrupted.
+					 */
+					LockBuffer(*buf, BUFFER_LOCK_UNLOCK);
+					in_retry = true;
+					continue;
+				}
+			}
 			lp = PageGetItemId(page, *off);
 			if (ItemIdIsUsed(lp))
 			{
