diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 5f0551a..f64a7eda 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6125,7 +6125,6 @@ StartupXLOG(void)
 		if (read_tablespace_map(&tablespaces))
 		{
 			ListCell   *lc;
-			struct stat st;
 
 			foreach(lc, tablespaces)
 			{
@@ -6136,27 +6135,9 @@ StartupXLOG(void)
 
 				/*
 				 * Remove the existing symlink if any and Create the symlink
-				 * under PGDATA.  We need to use rmtree instead of rmdir as
-				 * the link location might contain directories or files
-				 * corresponding to the actual path. Some tar utilities do
-				 * things that way while extracting symlinks.
+				 * under PGDATA.
 				 */
-				if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode))
-				{
-					if (!rmtree(linkloc,true))
-						ereport(ERROR,
-								(errcode_for_file_access(),
-								 errmsg("could not remove directory \"%s\": %m",
-										linkloc)));
-				}
-				else
-				{
-					if (unlink(linkloc) < 0 && errno != ENOENT)
-						ereport(ERROR,
-								(errcode_for_file_access(),
-								 errmsg("could not remove symbolic link \"%s\": %m",
-										linkloc)));
-				}
+				rmsymlink(linkloc);
 
 				if (symlink(ti->path, linkloc) < 0)
 					ereport(ERROR,
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 4ec1aff..76e62b2 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -627,31 +627,9 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
 
 	/*
 	 * In recovery, remove old symlink, in case it points to the wrong place.
-	 *
-	 * On Windows, junction points act like directories so we must be able to
-	 * apply rmdir; in general it seems best to make this code work like the
-	 * symlink removal code in destroy_tablespace_directories, except that
-	 * failure to remove is always an ERROR.
 	 */
 	if (InRecovery)
-	{
-		if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode))
-		{
-			if (rmdir(linkloc) < 0)
-				ereport(ERROR,
-						(errcode_for_file_access(),
-						 errmsg("could not remove directory \"%s\": %m",
-								linkloc)));
-		}
-		else
-		{
-			if (unlink(linkloc) < 0 && errno != ENOENT)
-				ereport(ERROR,
-						(errcode_for_file_access(),
-						 errmsg("could not remove symbolic link \"%s\": %m",
-								linkloc)));
-		}
-	}
+		rmsymlink(linkloc);
 
 	/*
 	 * Create the symlink under PGDATA
diff --git a/src/common/rmtree.c b/src/common/rmtree.c
index 75f47f7..8facfd5 100644
--- a/src/common/rmtree.c
+++ b/src/common/rmtree.c
@@ -129,3 +129,36 @@ rmtree(const char *path, bool rmtopdir)
 
 	return result;
 }
+
+#ifndef FRONTEND
+/*
+ *	rmsymlink
+ *
+ * This function removes symlinks.  On Windows, junction points act
+ * like directories so we must be able to apply rmdir.  This function
+ * works like the symlink removal code in destroy_tablespace_directories,
+ * except that failure to remove is always an ERROR.
+ */
+void
+rmsymlink(const char *linkloc)
+{
+	struct stat st;
+
+	if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode))
+	{
+		if (rmdir(linkloc) < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not remove directory \"%s\": %m",
+							linkloc)));
+	}
+	else
+	{
+		if (unlink(linkloc) < 0 && errno != ENOENT)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+						errmsg("could not remove symbolic link \"%s\": %m",
+							linkloc)));
+	}
+}
+#endif
diff --git a/src/include/port.h b/src/include/port.h
index 3787cbf..f2b19f9 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -256,6 +256,7 @@ extern bool pgwin32_is_junction(char *path);
 #endif
 
 extern bool rmtree(const char *path, bool rmtopdir);
+extern void rmsymlink(const char *linkloc);
 
 /*
  * stat() is not guaranteed to set the st_size field on win32, so we
