From 00a7c9014a8fbb7388a807daeba3e0a85b49a747 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Fri, 19 Aug 2011 11:20:30 -0400
Subject: [PATCH] In pg_upgrade, don't copy visibility map files from clusters
 that did not have crash-safe visibility maps to clusters that expect
 crash-safety.

Request from Robert Haas.
---
 contrib/pg_upgrade/pg_upgrade.h  |  6 ++++++
 contrib/pg_upgrade/relfilenode.c | 18 ++++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index 6def748ae8..a19b3df439 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -64,6 +64,12 @@
 #define TABLE_SPACE_SUBDIRS_CAT_VER 201001111
 /* postmaster/postgres -b (binary_upgrade) flag added during PG 9.1 development */
 #define BINARY_UPGRADE_SERVER_FLAG_CAT_VER 201104251
+/*
+ * 	Visibility map changed with this 9.2 commit,
+ *	8f9fe6edce358f7904e0db119416b4d1080a83aa; pick later catalog version.
+ */
+#define VISIBILITY_MAP_CRASHSAFE_CAT_VER 201107031
+
 
 /*
  * Each relation is represented by a relinfo structure.
diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
index d4a420fe2c..df752c5fad 100644
--- a/contrib/pg_upgrade/relfilenode.c
+++ b/contrib/pg_upgrade/relfilenode.c
@@ -120,9 +120,15 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
 	int			numFiles = 0;
 	int			mapnum;
 	int			fileno;
-
+	bool		vm_crashsafe_change = false;
+	
 	old_dir[0] = '\0';
 
+	/* Do not copy non-crashsafe vm files for binaries that assume crashsafety */
+	if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_CRASHSAFE_CAT_VER &&
+		new_cluster.controldata.cat_ver >= VISIBILITY_MAP_CRASHSAFE_CAT_VER)
+		vm_crashsafe_change = true;
+	
 	for (mapnum = 0; mapnum < size; mapnum++)
 	{
 		char		old_file[MAXPGPATH];
@@ -168,8 +174,16 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
 
 			for (fileno = 0; fileno < numFiles; fileno++)
 			{
+				char *vm_offset = strstr(namelist[fileno]->d_name, "_vm");
+				bool is_vm_file = false;
+
+				/* Is a visibility map file? (name ends with _vm) */
+				if (vm_offset && strlen(vm_offset) == strlen("_vm"))
+					is_vm_file = true;
+
 				if (strncmp(namelist[fileno]->d_name, scandir_file_pattern,
-							strlen(scandir_file_pattern)) == 0)
+							strlen(scandir_file_pattern)) == 0 &&
+					(!is_vm_file || !vm_crashsafe_change))
 				{
 					snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
 							 namelist[fileno]->d_name);
-- 
2.49.0