*** a/src/backend/access/transam/twophase.c
--- b/src/backend/access/transam/twophase.c
***************
*** 1457,1462 **** FinishPreparedTransaction(const char *gid, bool isCommit)
--- 1457,1463 ----
  	int			ndelrels;
  	SharedInvalidationMessage *invalmsgs;
  	int			i;
+ 	SMgrRelation *srels;
  
  	/*
  	 * Validate the GID, and lock the GXACT to ensure that two backends do not
***************
*** 1549,1561 **** FinishPreparedTransaction(const char *gid, bool isCommit)
  		delrels = abortrels;
  		ndelrels = hdr->nabortrels;
  	}
  	for (i = 0; i < ndelrels; i++)
! 	{
! 		SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
  
! 		smgrdounlink(srel, false);
! 		smgrclose(srel);
! 	}
  
  	/*
  	 * Handle cache invalidation messages.
--- 1550,1571 ----
  		delrels = abortrels;
  		ndelrels = hdr->nabortrels;
  	}
+ 
+ 	srels = palloc(sizeof(SMgrRelation) * ndelrels);
  	for (i = 0; i < ndelrels; i++)
! 		srels[i] = smgropen(delrels[i], InvalidBackendId);
  
! 	smgrdounlinkall(srels, ndelrels, false);
! 
! 	/*
! 	 * Call smgrclose() in reverse order as when smgropen() is called.
! 	 * This trick enables remove_from_unowned_list() in smgrclose()
! 	 * to search the SMgrRelation from the unowned list,
! 	 * in O(1) performance.
! 	 */
! 	for (i = ndelrels - 1; i >= 0; i--)
! 		smgrclose(srels[i]);
! 	pfree(srels);
  
  	/*
  	 * Handle cache invalidation messages.
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
***************
*** 5618,5623 **** xact_redo_commit(xl_xact_parsed_commit *parsed,
--- 5618,5625 ----
  	/* Make sure files supposed to be dropped are dropped */
  	if (parsed->nrels > 0)
  	{
+ 		SMgrRelation *srels;
+ 
  		/*
  		 * First update minimum recovery point to cover this WAL record. Once
  		 * a relation is deleted, there's no going back. The buffer manager
***************
*** 5635,5640 **** xact_redo_commit(xl_xact_parsed_commit *parsed,
--- 5637,5643 ----
  		 */
  		XLogFlush(lsn);
  
+ 		srels = palloc(sizeof(SMgrRelation) * parsed->nrels);
  		for (i = 0; i < parsed->nrels; i++)
  		{
  			SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
***************
*** 5642,5650 **** xact_redo_commit(xl_xact_parsed_commit *parsed,
  
  			for (fork = 0; fork <= MAX_FORKNUM; fork++)
  				XLogDropRelation(parsed->xnodes[i], fork);
! 			smgrdounlink(srel, true);
! 			smgrclose(srel);
  		}
  	}
  
  	/*
--- 5645,5664 ----
  
  			for (fork = 0; fork <= MAX_FORKNUM; fork++)
  				XLogDropRelation(parsed->xnodes[i], fork);
! 			srels[i] = srel;
  		}
+ 
+ 		smgrdounlinkall(srels, parsed->nrels, true);
+ 
+ 		/*
+ 		 * Call smgrclose() in reverse order as when smgropen() is called.
+ 		 * This trick enables remove_from_unowned_list() in smgrclose()
+ 		 * to search the SMgrRelation from the unowned list,
+ 		 * in O(1) performance.
+ 		 */
+ 		for (i = parsed->nrels - 1; i >= 0; i--)
+ 			smgrclose(srels[i]);
+ 		pfree(srels);
  	}
  
  	/*
***************
*** 5685,5690 **** xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
--- 5699,5705 ----
  {
  	int			i;
  	TransactionId max_xid;
+ 	SMgrRelation *srels;
  
  	Assert(TransactionIdIsValid(xid));
  
***************
*** 5748,5753 **** xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
--- 5763,5769 ----
  	}
  
  	/* Make sure files supposed to be dropped are dropped */
+ 	srels = palloc(sizeof(SMgrRelation) * parsed->nrels);
  	for (i = 0; i < parsed->nrels; i++)
  	{
  		SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
***************
*** 5755,5763 **** xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  			XLogDropRelation(parsed->xnodes[i], fork);
! 		smgrdounlink(srel, true);
! 		smgrclose(srel);
  	}
  }
  
  void
--- 5771,5790 ----
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  			XLogDropRelation(parsed->xnodes[i], fork);
! 		srels[i] = srel;
  	}
+ 
+ 	smgrdounlinkall(srels, parsed->nrels, true);
+ 
+ 	/*
+ 	 * Call smgrclose() in reverse order as when smgropen() is called.
+ 	 * This trick enables remove_from_unowned_list() in smgrclose()
+ 	 * to search the SMgrRelation from the unowned list,
+ 	 * in O(1) performance.
+ 	 */
+ 	for (i = parsed->nrels - 1; i >= 0; i--)
+ 		smgrclose(srels[i]);
+ 	pfree(srels);
  }
  
  void
