diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index ae83291..fbf91f5 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -84,6 +84,7 @@
 #include "access/twophase_rmgr.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "access/xlog_internal.h"
 #include "access/xloginsert.h"
 #include "access/xlogutils.h"
 #include "access/xlogreader.h"
@@ -2408,3 +2409,106 @@ PrepareRedoRemove(TransactionId xid, bool giveWarning)
 
 	return;
 }
+
+Datum
+pg_prepared_xact_status(PG_FUNCTION_ARGS)
+{
+    char const* gid = PG_GETARG_CSTRING(0);
+	XLogRecord *record;
+	XLogReaderState *xlogreader;
+	char	   *errormsg;
+	XLogRecPtr start_lsn;
+	XLogRecPtr lsn;
+	char const* xact_status = "unknown";
+	bool done = false;
+	TimeLineID timeline;
+	TransactionId xid = InvalidTransactionId;
+	XLogRecPtr wal_end = GetFlushRecPtr();
+
+	GetOldestRestartPoint(&start_lsn, &timeline);
+
+	xlogreader = XLogReaderAllocate(&read_local_xlog_page, NULL);
+	if (!xlogreader)
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory"),
+				 errdetail("Failed while allocating a WAL reading processor.")));
+	while (true)
+	{
+		lsn = start_lsn;
+		do
+		{
+			record = XLogReadRecord(xlogreader, lsn, &errormsg);
+			if (record == NULL)
+				break;
+			lsn = InvalidXLogRecPtr; /* continue after the record */
+			if (XLogRecGetRmid(xlogreader) == RM_XACT_ID)
+			{
+				uint32 info = XLogRecGetInfo(xlogreader);
+				switch (info & XLOG_XACT_OPMASK)
+				{
+				    case XLOG_XACT_PREPARE:
+					{
+						TwoPhaseFileHeader *hdr = (TwoPhaseFileHeader *)XLogRecGetData(xlogreader);
+						char* xact_gid = (char*)hdr + MAXALIGN(sizeof(TwoPhaseFileHeader));
+ 						if (strcmp(xact_gid, gid) == 0)
+						{
+							xid = hdr->xid;
+							xact_status = "prepared";
+						}
+						break;
+					}
+				    case XLOG_XACT_COMMIT_PREPARED:
+					{
+						xl_xact_commit *xlrec;
+						xl_xact_parsed_commit parsed;
+
+						xlrec = (xl_xact_commit *) XLogRecGetData(xlogreader);
+						ParseCommitRecord(info, xlrec, &parsed);
+						if (xid == parsed.twophase_xid)
+						{
+							Assert(TransactionIdIsValid(xid));
+							xact_status = "committed";
+							done = true;
+						}
+						break;
+					}
+				    case XLOG_XACT_ABORT_PREPARED:
+					{
+						xl_xact_abort *xlrec;
+						xl_xact_parsed_abort parsed;
+
+						xlrec = (xl_xact_abort *) XLogRecGetData(xlogreader);
+						ParseAbortRecord(info, xlrec, &parsed);
+						if (xid == parsed.twophase_xid)
+						{
+							Assert(TransactionIdIsValid(xid));
+							xact_status = "aborted";
+							done = true;
+						}
+						break;
+					}
+				    default:
+					    break;
+				}
+			}
+		} while (!done && xlogreader->EndRecPtr < wal_end);
+
+		if (done)
+			break;
+
+		lsn = start_lsn;
+		XLogSegNoOffsetToRecPtr(lsn/XLogSegSize, 0, start_lsn);
+		start_lsn = XLogFindNextRecord(xlogreader, start_lsn);
+		if (start_lsn == lsn)
+		{
+			if (lsn <= XLogSegSize)
+				break;
+			XLogSegNoOffsetToRecPtr(lsn/XLogSegSize-1, 0, start_lsn);
+			start_lsn = XLogFindNextRecord(xlogreader, start_lsn);
+		}
+	} 
+
+	XLogReaderFree(xlogreader);
+	PG_RETURN_CSTRING(xact_status);
+}
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 0781a7b..bdc552c 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -849,7 +849,6 @@ ValidXLogPageHeader(XLogReaderState *state, XLogRecPtr recptr,
 	return true;
 }
 
-#ifdef FRONTEND
 /*
  * Functions that are currently not needed in the backend, but are better
  * implemented inside xlogreader.c because of the internal facilities available
@@ -974,8 +973,6 @@ out:
 	return found;
 }
 
-#endif							/* FRONTEND */
-
 
 /* ----------------------------------------
  * Functions for decoding the data and block references in a record.
diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h
index 7671598..743f220 100644
--- a/src/include/access/xlogreader.h
+++ b/src/include/access/xlogreader.h
@@ -202,9 +202,7 @@ extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,
 /* Invalidate read state */
 extern void XLogReaderInvalReadState(XLogReaderState *state);
 
-#ifdef FRONTEND
 extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr);
-#endif							/* FRONTEND */
 
 /* Functions for decoding an XLogRecord */
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 8b33b4e..001f586 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3148,6 +3148,10 @@ DATA(insert OID = 3378 (  pg_isolation_test_session_is_blocked PGNSP PGUID 12 1
 DESCR("isolationtester support function");
 DATA(insert OID = 1065 (  pg_prepared_xact PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ _null_ pg_prepared_xact _null_ _null_ _null_ ));
 DESCR("view two-phase transactions");
+
+DATA(insert OID = 6015  (  pg_prepared_xact_status	PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2275 "2275" _null_ _null_ _null_ _null_ _null_ pg_prepared_xact_status _null_ _null_ _null_ ));
+DESCR("I/O");
+
 DATA(insert OID = 3819 (  pg_get_multixact_members PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 1 0 2249 "28" "{28,28,25}" "{i,o,o}" "{multixid,xid,mode}" _null_ _null_ pg_get_multixact_members _null_ _null_ _null_ ));
 DESCR("view members of a multixactid");
 
