diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 6db46c0..c01b170 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1356,12 +1356,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
 	for (i = 0; i < ndelrels; i++)
 	{
 		SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
-		ForkNumber	fork;
-
-		for (fork = 0; fork <= MAX_FORKNUM; fork++)
-		{
-			smgrdounlink(srel, fork, false);
-		}
+		smgrdounlink(srel, AllForks, false);
 		smgrclose(srel);
 	}
 
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 5ae46de..a117660 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -4633,13 +4633,8 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
 	for (i = 0; i < nrels; i++)
 	{
 		SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId);
-		ForkNumber	fork;
-
-		for (fork = 0; fork <= MAX_FORKNUM; fork++)
-		{
-			XLogDropRelation(xnodes[i], fork);
-			smgrdounlink(srel, fork, true);
-		}
+		XLogDropRelation(xnodes[i], AllForks);
+		smgrdounlink(srel, AllForks, true);
 		smgrclose(srel);
 	}
 
@@ -4773,13 +4768,8 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
 	for (i = 0; i < xlrec->nrels; i++)
 	{
 		SMgrRelation srel = smgropen(xlrec->xnodes[i], InvalidBackendId);
-		ForkNumber	fork;
-
-		for (fork = 0; fork <= MAX_FORKNUM; fork++)
-		{
-			XLogDropRelation(xlrec->xnodes[i], fork);
-			smgrdounlink(srel, fork, true);
-		}
+		XLogDropRelation(xlrec->xnodes[i], AllForks);
+		smgrdounlink(srel, AllForks, true);
 		smgrclose(srel);
 	}
 }
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index f286cdf..2578585 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -148,7 +148,7 @@ forget_invalid_pages(RelFileNode node, ForkNumber forkno, BlockNumber minblkno)
 	while ((hentry = (xl_invalid_page *) hash_seq_search(&status)) != NULL)
 	{
 		if (RelFileNodeEquals(hentry->key.node, node) &&
-			hentry->key.forkno == forkno &&
+			(hentry->key.forkno == forkno || forkno == AllForks) &&
 			hentry->key.blkno >= minblkno)
 		{
 			if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2)
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index a017101..b871604 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -356,13 +356,9 @@ smgrDoPendingDeletes(bool isCommit)
 			if (pending->atCommit == isCommit)
 			{
 				SMgrRelation srel;
-				int			i;
 
 				srel = smgropen(pending->relnode, pending->backend);
-				for (i = 0; i <= MAX_FORKNUM; i++)
-				{
-					smgrdounlink(srel, i, false);
-				}
+				smgrdounlink(srel, AllForks, false);
 				smgrclose(srel);
 			}
 			/* must explicitly free the list entry */
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index a1b588b..124983c 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2061,7 +2061,8 @@ DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber forkNum,
 
 		LockBufHdr(bufHdr);
 		if (RelFileNodeEquals(bufHdr->tag.rnode, rnode.node) &&
-			bufHdr->tag.forkNum == forkNum &&
+			(bufHdr->tag.forkNum == forkNum ||
+			 forkNum == AllForks) &&
 			bufHdr->tag.blockNum >= firstDelBlock)
 			InvalidateBuffer(bufHdr);	/* releases spinlock */
 		else
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 5f87543..c875606 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -343,9 +343,16 @@ smgrdounlink(SMgrRelation reln, ForkNumber forknum, bool isRedo)
 {
 	RelFileNodeBackend rnode = reln->smgr_rnode;
 	int			which = reln->smgr_which;
+	int			i;
 
 	/* Close the fork */
-	(*(smgrsw[which].smgr_close)) (reln, forknum);
+	if (forknum == AllForks)
+	{
+		for (i = 0; i <= MAX_FORKNUM; i++)
+			(*(smgrsw[which].smgr_close)) (reln, i);
+	}
+	else
+		(*(smgrsw[which].smgr_close)) (reln, forknum);
 
 	/*
 	 * Get rid of any remaining buffers for the relation.  bufmgr will just
@@ -377,7 +384,13 @@ smgrdounlink(SMgrRelation reln, ForkNumber forknum, bool isRedo)
 	 * ERROR, because we've already decided to commit or abort the current
 	 * xact.
 	 */
-	(*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
+	if (forknum == AllForks)
+	{
+		for (i = 0; i <= MAX_FORKNUM; i++)
+			(*(smgrsw[which].smgr_unlink)) (rnode, i, isRedo);
+	}
+	else
+		(*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
 }
 
 /*
diff --git a/src/include/storage/relfilenode.h b/src/include/storage/relfilenode.h
index 60c3829..451139c 100644
--- a/src/include/storage/relfilenode.h
+++ b/src/include/storage/relfilenode.h
@@ -20,10 +20,12 @@
  * The physical storage of a relation consists of one or more forks. The
  * main fork is always created, but in addition to that there can be
  * additional forks for storing various metadata. ForkNumber is used when
- * we need to refer to a specific fork in a relation.
+ * we need to refer to a specific fork in a relation, or AllForks
+ * can be used in places to refer to all forks of a relation.
  */
 typedef enum ForkNumber
 {
+	AllForks = -2,
 	InvalidForkNumber = -1,
 	MAIN_FORKNUM = 0,
 	FSM_FORKNUM,