diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index ee22c267c1..b0983c7ea1 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -386,9 +386,10 @@ Indexes:
     The recommended recovery method in such cases is to drop the invalid
     index and try again to perform <command>REINDEX CONCURRENTLY</command>.
     The concurrent index created during the processing has a name ending in
-    the suffix <literal>ccnew</literal>, or <literal>ccold</literal> if it is an old index definition which we failed
-    to drop. Invalid indexes can be dropped using <literal>DROP INDEX</literal>,
-    including invalid toast indexes.
+    the suffix <literal>ccnew</literal>, or <literal>ccold</literal> if it
+    is an old index definition which we failed to drop. Invalid indexes can
+    be dropped using <literal>DROP INDEX</literal>, including invalid toast
+    indexes.
    </para>
 
    <para>
@@ -396,9 +397,9 @@ Indexes:
     table to occur in parallel, but only one concurrent index build can
     occur on a table at a time. In both cases, no other types of schema
     modification on the table are allowed meanwhile.  Another difference
-    is that a regular <command>REINDEX TABLE</command> or <command>REINDEX INDEX</command>
-    command can be performed within a transaction block, but
-    <command>REINDEX CONCURRENTLY</command> cannot.
+    is that a regular <command>REINDEX TABLE</command> or
+    <command>REINDEX INDEX</command> command can be performed within a
+    transaction block, but <command>REINDEX CONCURRENTLY</command> cannot.
    </para>
 
    <para>
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9b3a742663..b84c05736f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -693,7 +693,6 @@ UpdateIndexRelation(Oid indexoid,
  * classObjectId: array of index opclass OIDs, one per index column
  * coloptions: array of per-index-column indoption settings
  * reloptions: AM-specific options
- * tupdesc: Tuple descriptor used for the index if defined
  * flags: bitmask that can include any combination of these bits:
  *		INDEX_CREATE_IS_PRIMARY
  *			the index is a primary key
@@ -734,7 +733,6 @@ index_create(Relation heapRelation,
 			 Oid *classObjectId,
 			 int16 *coloptions,
 			 Datum reloptions,
-			 TupleDesc tupdesc,
 			 bits16 flags,
 			 bits16 constr_flags,
 			 bool allow_system_table_mods,
@@ -742,6 +740,7 @@ index_create(Relation heapRelation,
 			 Oid *constraintId)
 {
 	Oid			heapRelationId = RelationGetRelid(heapRelation);
+	Oid			heapNamespaceId = get_rel_namespace(heapRelationId);
 	Relation	pg_class;
 	Relation	indexRelation;
 	TupleDesc	indexTupDesc;
@@ -794,10 +793,12 @@ index_create(Relation heapRelation,
 
 	/*
 	 * concurrent index build on a system catalog is unsafe because we tend to
-	 * release locks before committing in catalogs
+	 * release locks before committing in catalogs.  Toast catalogs are fine
+	 * though as they are associated with a root relation which could be
+	 * reindexed concurrently.
 	 */
 	if (concurrent &&
-		IsSystemNamespace(get_rel_namespace(heapRelationId)))
+		IsSystemNamespace(heapNamespaceId))
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("concurrent index creation on system catalog tables is not supported")));
@@ -865,20 +866,14 @@ index_create(Relation heapRelation,
 	}
 
 	/*
-	 * construct tuple descriptor for index tuples if not passed by caller
+	 * construct tuple descriptor for index tuples
 	 */
-	if (!tupdesc)
-		indexTupDesc = ConstructTupleDescriptor(heapRelation,
-												indexInfo,
-												indexColNames,
-												accessMethodObjectId,
-												collationObjectId,
-												classObjectId);
-	else
-	{
-		Assert(indexColNames == NIL);
-		indexTupDesc = tupdesc;
-	}
+	indexTupDesc = ConstructTupleDescriptor(heapRelation,
+											indexInfo,
+											indexColNames,
+											accessMethodObjectId,
+											collationObjectId,
+											classObjectId);
 
 	/*
 	 * Allocate an OID for the index, unless we were told what to use.
@@ -1210,14 +1205,15 @@ index_create(Relation heapRelation,
 }
 
 /*
- * index_concurrently_create_copy
+ * index_create_copy_concurrent
  *
  * Create concurrently an index based on the definition of the one provided by
  * caller.  The index is inserted into catalogs and needs to be built later
  * on.  This is called during concurrent reindex processing.
  */
 Oid
-index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char *newName)
+index_create_copy_concurrent(Relation heapRelation, Oid oldIndexId,
+							 const char *newName)
 {
 	Relation	indexRelation;
 	IndexInfo  *indexInfo;
@@ -1231,6 +1227,8 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
 	oidvector  *indclass;
 	int2vector *indcoloptions;
 	bool		isnull;
+	List	   *indexColNames = NIL;
+	int			i;
 
 	indexRelation = index_open(oldIndexId, RowExclusiveLock);
 
@@ -1242,9 +1240,6 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
 	indexInfo->ii_ExclusionProcs = NULL;
 	indexInfo->ii_ExclusionStrats = NULL;
 
-	/* Create a copy of the tuple descriptor to be used for the new entry */
-	indexTupDesc = CreateTupleDescCopyConstr(RelationGetDescr(indexRelation));
-
 	/* Get the array of class and column options IDs from index info */
 	indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(oldIndexId));
 	if (!HeapTupleIsValid(indexTuple))
@@ -1266,6 +1261,19 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
 	optionDatum = SysCacheGetAttr(RELOID, classTuple,
 								  Anum_pg_class_reloptions, &isnull);
 
+	/*
+	 * Extract the list of column names to be used for the index
+	 * creation.
+	 */
+	indexTupDesc = RelationGetDescr(indexRelation);
+	for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+	{
+		Form_pg_attribute att = TupleDescAttr(indexTupDesc, i);
+
+		/* Grab the column name and save it to the list */
+		indexColNames = lappend(indexColNames, NameStr(att->attname));
+	}
+
 	/* Now create the new index */
 	newIndexId = index_create(heapRelation,
 							  newName,
@@ -1274,14 +1282,13 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
 							  InvalidOid,	/* parentConstraintId */
 							  InvalidOid,	/* relFileNode */
 							  indexInfo,
-							  NIL,
+							  indexColNames,
 							  indexRelation->rd_rel->relam,
 							  indexRelation->rd_rel->reltablespace,
 							  indexRelation->rd_indcollation,
 							  indclass->values,
 							  indcoloptions->values,
 							  optionDatum,
-							  indexTupDesc,
 							  INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT,
 							  0,
 							  true,	/* allow table to be a system catalog? */
@@ -1297,20 +1304,24 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
 }
 
 /*
- * index_concurrently_build
+ * index_build_concurrent
  *
  * Build index for a concurrent operation.  Low-level locks are taken when
- * this operation is performed to prevent only schema changes, but they need to
- * be kept until the end of the transaction performing this operation.
+ * this operation is performed to prevent only schema changes, but they need
+ * to be kept until the end of the transaction performing this operation.
+ * 'indexOid' refers to an index relation OID already created as part of
+ * previous processing, and 'heapOid' refers to its parent heap relation.
  */
 void
-index_concurrently_build(Oid heapOid,
-						 Oid indexOid)
+index_build_concurrent(Oid heapOid, Oid indexOid)
 {
 	Relation	heapRel,
 				indexRelation;
 	IndexInfo  *indexInfo;
 
+	/* This had better make sure that a snapshot is active */
+	Assert(ActiveSnapshotSet());
+
 	/* Open and lock the parent heap relation */
 	heapRel = table_open(heapOid, ShareUpdateExclusiveLock);
 
@@ -1344,13 +1355,13 @@ index_concurrently_build(Oid heapOid,
 }
 
 /*
- * index_concurrently_swap
+ * index_swap_concurrent
  *
  * Swap name, dependencies, and constraints of the old index over to the new
  * index, while marking the old index as invalid and the new as valid.
  */
 void
-index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
+index_swap_concurrent(Oid newIndexId, Oid oldIndexId, const char *oldName)
 {
 	Relation	pg_class,
 				pg_index,
@@ -1417,8 +1428,8 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 	newIndexForm = (Form_pg_index) GETSTRUCT(newIndexTuple);
 
 	/*
-	 * Copy constraint flags for old index. This is safe because the old index
-	 * guaranteed uniqueness.
+	 * Copy conntraint flags from the old index. This is safe because the old
+	 * index guaranteed uniqueness.
 	 */
 	newIndexForm->indisprimary = oldIndexForm->indisprimary;
 	oldIndexForm->indisprimary = false;
@@ -1509,7 +1520,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 	}
 
 	/*
-	 * Move comment if any
+	 * Move comment if any.
 	 */
 	{
 		Relation	description;
@@ -1555,7 +1566,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 	}
 
 	/*
-	 * Move all dependencies on the old index to the new
+	 * Move all dependencies on the old index to the new one.
 	 */
 
 	if (OidIsValid(indexConstraintOid))
@@ -1592,7 +1603,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 }
 
 /*
- * index_concurrently_set_dead
+ * index_set_dead_concurrent
  *
  * Perform the last invalidation stage of DROP INDEX CONCURRENTLY or REINDEX
  * CONCURRENTLY before actually dropping the index. After calling this
@@ -1601,7 +1612,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
  * function.
  */
 void
-index_concurrently_set_dead(Oid heapOid, Oid indexOid)
+index_set_dead_concurrent(Oid heapOid, Oid indexOid)
 {
 	Relation	heapRelation,
 				indexRelation;
@@ -1638,7 +1649,7 @@ index_concurrently_set_dead(Oid heapOid, Oid indexOid)
 }
 
 /*
- * index_concurrently_drop
+ * index_drop_concurrent
  *
  * Drop a single index concurrently as the last step of an index concurrent
  * process. Deletion is done through performDeletion or dependencies of the
@@ -1648,7 +1659,7 @@ index_concurrently_set_dead(Oid heapOid, Oid indexOid)
  * server sessions.
  */
 void
-index_concurrently_drop(Oid indexId)
+index_drop_concurrent(Oid indexId)
 {
 	Oid			constraintOid = get_index_constraint(indexId);
 	ObjectAddress object;
@@ -2089,7 +2100,7 @@ index_drop(Oid indexId, bool concurrent)
 		WaitForLockers(heaplocktag, AccessExclusiveLock);
 
 		/* Finish invalidation of index and mark it as dead */
-		index_concurrently_set_dead(heapId, indexId);
+		index_set_dead_concurrent(heapId, indexId);
 
 		/*
 		 * Again, commit the transaction to make the pg_index update visible
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 969b34e752..b5b8f62b19 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -395,7 +395,7 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
 	ObjectAddress objAddr;
 	bool		newIsPinned;
 
-	depRel = heap_open(DependRelationId, RowExclusiveLock);
+	depRel = table_open(DependRelationId, RowExclusiveLock);
 
 	/*
 	 * If oldRefObjectId is pinned, there won't be any dependency entries on
@@ -838,7 +838,7 @@ get_index_ref_constraints(Oid indexId)
 	HeapTuple	tup;
 
 	/* Search the dependency table for the index */
-	depRel = heap_open(DependRelationId, AccessShareLock);
+	depRel = table_open(DependRelationId, AccessShareLock);
 
 	ScanKeyInit(&key[0],
 				Anum_pg_depend_refclassid,
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index fb93c41c88..77be19175a 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -336,7 +336,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 				 list_make2("chunk_id", "chunk_seq"),
 				 BTREE_AM_OID,
 				 rel->rd_rel->reltablespace,
-				 collationObjectId, classObjectId, coloptions, (Datum) 0, NULL,
+				 collationObjectId, classObjectId, coloptions, (Datum) 0,
 				 INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL);
 
 	table_close(toast_rel, NoLock);
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index a3b6aed0a7..8a80308c3b 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -305,15 +305,15 @@ CheckIndexCompatible(Oid oldId,
  * Wait for transactions that might have an older snapshot than the given xmin
  * limit, because it might not contain tuples deleted just before it has
  * been taken. Obtain a list of VXIDs of such transactions, and wait for them
- * individually.
+ * individually.  This is used when building concurrently an index.
  *
  * We can exclude any running transactions that have xmin > the xmin given;
  * their oldest snapshot must be newer than our xmin limit.
  * We can also exclude any transactions that have xmin = zero, since they
  * evidently have no live snapshot at all (and any one they might be in
  * process of taking is certainly newer than ours).  Transactions in other
- * DBs can be ignored too, since they'll never even be able to see this
- * index.
+ * DBs can be ignored too, since they'll never even be able to see the
+ * index worked on.
  *
  * We can also exclude autovacuum processes and processes running manual
  * lazy VACUUMs, because they won't be fazed by missing index entries
@@ -937,7 +937,7 @@ DefineIndex(Oid relationId,
 					 stmt->oldNode, indexInfo, indexColNames,
 					 accessMethodId, tablespaceId,
 					 collationObjectId, classObjectId,
-					 coloptions, reloptions, NULL,
+					 coloptions, reloptions,
 					 flags, constr_flags,
 					 allowSystemTableMods, !check_rights,
 					 &createdConstraintId);
@@ -1237,10 +1237,7 @@ DefineIndex(Oid relationId,
 	PushActiveSnapshot(GetTransactionSnapshot());
 
 	/* Perform concurrent build of index */
-	index_concurrently_build(RangeVarGetRelid(stmt->relation,
-											  ShareUpdateExclusiveLock,
-											  false),
-							 indexRelationId);
+	index_build_concurrent(relationId, indexRelationId);
 
 	/* we can do away with our snapshot */
 	PopActiveSnapshot();
@@ -2814,9 +2811,9 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 											false);
 
 		/* Create new index definition based on given index */
-		concurrentOid = index_concurrently_create_copy(indexParentRel,
-													   indOid,
-													   concurrentName);
+		concurrentOid = index_create_copy_concurrent(indexParentRel,
+													 indOid,
+													 concurrentName);
 
 		/* Now open the relation of the new index, a lock is also needed on it */
 		indexConcurrentRel = index_open(concurrentOid, ShareUpdateExclusiveLock);
@@ -2851,7 +2848,8 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 	 */
 	foreach(lc, parentRelationIds)
 	{
-		Relation	heapRelation = table_open(lfirst_oid(lc), ShareUpdateExclusiveLock);
+		Relation	heapRelation = table_open(lfirst_oid(lc),
+											  ShareUpdateExclusiveLock);
 		LockRelId	lockrelid = heapRelation->rd_lockInfo.lockRelId;
 		LOCKTAG    *heaplocktag;
 
@@ -2914,7 +2912,6 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 		Relation	indexRel;
 		Oid			indOid = lfirst_oid(lc);
 		Oid			concurrentOid = lfirst_oid(lc2);
-		Oid			tableOid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -2926,14 +2923,15 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 
 		/*
 		 * Index relation has been closed by previous commit, so reopen it to
-		 * get its information.
+		 * determine if it is used as a primary key.
 		 */
 		indexRel = index_open(indOid, ShareUpdateExclusiveLock);
-		tableOid = indexRel->rd_index->indrelid;
-		index_close(indexRel, NoLock);
 
 		/* Perform concurrent build of new index */
-		index_concurrently_build(tableOid, concurrentOid);
+		index_build_concurrent(indexRel->rd_index->indrelid, concurrentOid);
+
+		/* Keep lock until the end of this transaction */
+		index_close(indexRel, NoLock);
 
 		/* We can do away with our snapshot */
 		PopActiveSnapshot();
@@ -3045,7 +3043,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 									 false);
 
 		/* Swap old index with the new one */
-		index_concurrently_swap(concurrentOid, indOid, oldName);
+		index_swap_concurrent(concurrentOid, indOid, oldName);
 
 		/*
 		 * Invalidate the relcache for the table, so that after this commit
@@ -3090,7 +3088,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 		relOid = IndexGetRelation(indOid, false);
 
 		/* Finish the index invalidation and set it as dead. */
-		index_concurrently_set_dead(relOid, indOid);
+		index_set_dead_concurrent(relOid, indOid);
 	}
 
 	/* Commit this transaction to make the updates visible. */
@@ -3118,14 +3116,14 @@ ReindexRelationConcurrently(Oid relationOid, int options)
 
 		CHECK_FOR_INTERRUPTS();
 
-		index_concurrently_drop(indOid);
+		index_drop_concurrent(indOid);
 	}
 
 	PopActiveSnapshot();
 	CommitTransactionCommand();
 
 	/*
-	 * Finallt release the session-level lock on the parent table.
+	 * Finally release the session-level lock on the parent table.
 	 */
 	foreach(lc, relationLocks)
 	{
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 84dd900dd6..803fa6a2c8 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -65,7 +65,6 @@ extern Oid index_create(Relation heapRelation,
 			 Oid *classObjectId,
 			 int16 *coloptions,
 			 Datum reloptions,
-			 TupleDesc tupdesc,
 			 bits16 flags,
 			 bits16 constr_flags,
 			 bool allow_system_table_mods,
@@ -78,22 +77,6 @@ extern Oid index_create(Relation heapRelation,
 #define	INDEX_CONSTR_CREATE_UPDATE_INDEX	(1 << 3)
 #define	INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS	(1 << 4)
 
-extern Oid index_concurrently_create_copy(Relation heapRelation,
-										  Oid oldIndexId,
-										  const char *newName);
-
-extern void index_concurrently_build(Oid heapOid,
-									 Oid indexOid);
-
-extern void index_concurrently_swap(Oid newIndexId,
-									Oid oldIndexId,
-									const char *oldName);
-
-extern void index_concurrently_set_dead(Oid heapOid,
-										Oid indexOid);
-
-extern void index_concurrently_drop(Oid indexId);
-
 extern ObjectAddress index_constraint_create(Relation heapRelation,
 						Oid indexRelationId,
 						Oid parentConstraintId,
@@ -127,6 +110,21 @@ extern void index_build(Relation heapRelation,
 			bool isreindex,
 			bool parallel);
 
+extern void index_build_concurrent(Oid heapOid, Oid indexOid);
+
+extern Oid index_create_copy_concurrent(Relation heapRelation,
+										Oid oldIndexId,
+										const char *newName);
+
+extern void index_swap_concurrent(Oid newIndexId,
+								  Oid oldIndexId,
+								  const char *oldName);
+
+extern void index_set_dead_concurrent(Oid heapOid,
+									  Oid indexOid);
+
+extern void index_drop_concurrent(Oid indexId);
+
 extern double IndexBuildHeapScan(Relation heapRelation,
 				   Relation indexRelation,
 				   IndexInfo *indexInfo,
