*** a/src/backend/access/transam/twophase.c
--- b/src/backend/access/transam/twophase.c
***************
*** 1456,1462 **** FinishPreparedTransaction(const char *gid, bool isCommit)
  	RelFileNode *delrels;
  	int			ndelrels;
  	SharedInvalidationMessage *invalmsgs;
- 	int			i;
  
  	/*
  	 * Validate the GID, and lock the GXACT to ensure that two backends do not
--- 1456,1461 ----
***************
*** 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.
--- 1548,1556 ----
  		delrels = abortrels;
  		ndelrels = hdr->nabortrels;
  	}
  
! 	/* Make sure files supposed to be dropped are dropped */
! 	DropRelationFiles(delrels, ndelrels, false);
  
  	/*
  	 * Handle cache invalidation messages.
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
***************
*** 5516,5522 **** xact_redo_commit(xl_xact_parsed_commit *parsed,
  				 RepOriginId origin_id)
  {
  	TransactionId max_xid;
- 	int			i;
  	TimestampTz commit_time;
  
  	Assert(TransactionIdIsValid(xid));
--- 5516,5521 ----
***************
*** 5635,5650 **** xact_redo_commit(xl_xact_parsed_commit *parsed,
  		 */
  		XLogFlush(lsn);
  
! 		for (i = 0; i < parsed->nrels; i++)
! 		{
! 			SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
! 			ForkNumber	fork;
! 
! 			for (fork = 0; fork <= MAX_FORKNUM; fork++)
! 				XLogDropRelation(parsed->xnodes[i], fork);
! 			smgrdounlink(srel, true);
! 			smgrclose(srel);
! 		}
  	}
  
  	/*
--- 5634,5641 ----
  		 */
  		XLogFlush(lsn);
  
! 		/* Make sure files supposed to be dropped are dropped */
! 		DropRelationFiles(parsed->xnodes, parsed->nrels, true);
  	}
  
  	/*
***************
*** 5683,5689 **** xact_redo_commit(xl_xact_parsed_commit *parsed,
  static void
  xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
  {
- 	int			i;
  	TransactionId max_xid;
  
  	Assert(TransactionIdIsValid(xid));
--- 5674,5679 ----
***************
*** 5748,5763 **** xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
  	}
  
  	/* Make sure files supposed to be dropped are dropped */
! 	for (i = 0; i < parsed->nrels; i++)
! 	{
! 		SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
! 		ForkNumber	fork;
! 
! 		for (fork = 0; fork <= MAX_FORKNUM; fork++)
! 			XLogDropRelation(parsed->xnodes[i], fork);
! 		smgrdounlink(srel, true);
! 		smgrclose(srel);
! 	}
  }
  
  void
--- 5738,5744 ----
  	}
  
  	/* Make sure files supposed to be dropped are dropped */
! 	DropRelationFiles(parsed->xnodes, parsed->nrels, true);
  }
  
  void
*** a/src/backend/storage/smgr/md.c
--- b/src/backend/storage/smgr/md.c
***************
*** 26,31 ****
--- 26,32 ----
  #include <sys/file.h>
  
  #include "miscadmin.h"
+ #include "access/xlogutils.h"
  #include "access/xlog.h"
  #include "pgstat.h"
  #include "portability/instr_time.h"
***************
*** 1703,1708 **** ForgetDatabaseFsyncRequests(Oid dbid)
--- 1704,1746 ----
  	}
  }
  
+ /*
+  * DropRelationFiles -- drop files of all given relations
+  */
+ void
+ DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo)
+ {
+ 	SMgrRelation *srels;
+ 	int			i;
+ 
+ 	srels = palloc(sizeof(SMgrRelation) * ndelrels);
+ 	for (i = 0; i < ndelrels; i++)
+ 	{
+ 		SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
+ 
+ 		if (isRedo)
+ 		{
+ 			ForkNumber	fork;
+ 
+ 			for (fork = 0; fork <= MAX_FORKNUM; fork++)
+ 				XLogDropRelation(delrels[i], fork);
+ 		}
+ 		srels[i] = srel;
+ 	}
+ 
+ 	smgrdounlinkall(srels, ndelrels, isRedo);
+ 
+ 	/*
+ 	 * 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);
+ }
+ 
  
  /*
   *	_fdvec_resize() -- Resize the fork's open segments array
*** a/src/include/storage/smgr.h
--- b/src/include/storage/smgr.h
***************
*** 143,147 **** extern void RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum,
--- 143,148 ----
  					 BlockNumber segno);
  extern void ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum);
  extern void ForgetDatabaseFsyncRequests(Oid dbid);
+ extern void DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo);
  
  #endif							/* SMGR_H */
