From c2e603f95a0b66a924e854fc2a0cb08b75eb55ea Mon Sep 17 00:00:00 2001
From: "suyu.cmj" <mengjuan.cmj@alibaba-inc.com>
Date: Mon, 14 Jul 2025 01:59:26 +0000
Subject: [PATCH] Fix 2PC file check logic in PrepareRedoAdd()

In commit cb0cca1880723b4c90c56cdcf3842489ef036800,
the 2PC state file check logic is added in PrepareRedoAdd()
to fix the bug of 2PC recovery. Each time a file is accessed,
the OS creates a dentry for it and increases the reference
count of the parent directory's dentry. The type of the dentry
reference count is int32. When there are many 2PC transactions,
this logic may lead to an overflow of the parent dentry's
reference count, which could ultimately cause the OS to crash.
Since the 2PC data on disk is only restored at the beginning
of recovery with restoreTwoPhaseData(), after reaching a
consistent state, the 2PC transactions are only added from the
WAL. So we perform the file access check only when the server
has not yet reached a consistent state. Once consistency has
been reached, if a duplicate 2PC transaction is added, it will
directly result in an error in the subsequent replay logic.
---
 src/backend/access/transam/twophase.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 85cbe397cb..b69aca0977 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -2520,8 +2520,16 @@ PrepareRedoAdd(FullTransactionId fxid, char *buf,
 	 * duplicates in TwoPhaseState.  If a consistent state has been reached,
 	 * the record is added to TwoPhaseState and it should have no
 	 * corresponding file in pg_twophase.
+	 *
+	 * When there are many 2PC transactions, frequently accessing empty files
+	 * may lead to an increase in OS slab memory. In worse cases, this could
+	 * cause the reference count of the directory dentry to overflow,
+	 * potentially resulting in an OS crash. Therefore, this check is only
+	 * performed when a consistent state has not yet been reached. Once
+	 * consistency has been reached, if a duplicate 2PC transaction is added,
+	 * it will directly result in an error in the subsequent replay logic.
 	 */
-	if (!XLogRecPtrIsInvalid(start_lsn))
+	if (!XLogRecPtrIsInvalid(start_lsn) && !reachedConsistency)
 	{
 		char		path[MAXPGPATH];
 
@@ -2530,7 +2538,7 @@ PrepareRedoAdd(FullTransactionId fxid, char *buf,
 
 		if (access(path, F_OK) == 0)
 		{
-			ereport(reachedConsistency ? ERROR : WARNING,
+			ereport(WARNING,
 					(errmsg("could not recover two-phase state file for transaction %u",
 							hdr->xid),
 					 errdetail("Two-phase state file has been found in WAL record %X/%08X, but this transaction has already been restored from disk.",
-- 
2.27.0

