diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
new file mode 100644
index 33a867f..0a49a23
*** a/contrib/pg_upgrade/relfilenode.c
--- b/contrib/pg_upgrade/relfilenode.c
***************
*** 17,25 ****
  
  static void transfer_single_new_db(pageCnvCtx *pageConverter,
  					   FileNameMap *maps, int size);
! static void transfer_relfile(pageCnvCtx *pageConverter,
! 				 const char *fromfile, const char *tofile,
! 				 const char *nspname, const char *relname);
  
  
  /*
--- 17,24 ----
  
  static void transfer_single_new_db(pageCnvCtx *pageConverter,
  					   FileNameMap *maps, int size);
! static int transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
! 							 const char *suffix);
  
  
  /*
*************** static void
*** 131,185 ****
  transfer_single_new_db(pageCnvCtx *pageConverter,
  					   FileNameMap *maps, int size)
  {
- 	char		old_dir[MAXPGPATH];
- 	char		file_pattern[MAXPGPATH];
- 	char		**namelist = NULL;
- 	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];
! 		char		new_file[MAXPGPATH];
! 
! 		/* Changed tablespaces?  Need a new directory scan? */
! 		if (strcmp(maps[mapnum].old_dir, old_dir) != 0)
! 		{
! 			if (numFiles > 0)
! 			{
! 				for (fileno = 0; fileno < numFiles; fileno++)
! 					pg_free(namelist[fileno]);
! 				pg_free(namelist);
! 			}
! 
! 			snprintf(old_dir, sizeof(old_dir), "%s", maps[mapnum].old_dir);
! 			numFiles = load_directory(old_dir, &namelist);
! 		}
! 
! 		/* Copying files might take some time, so give feedback. */
! 
! 		snprintf(old_file, sizeof(old_file), "%s/%u", maps[mapnum].old_dir,
! 				 maps[mapnum].old_relfilenode);
! 		snprintf(new_file, sizeof(new_file), "%s/%u", maps[mapnum].new_dir,
! 				 maps[mapnum].new_relfilenode);
! 		pg_log(PG_REPORT, OVERWRITE_MESSAGE, old_file);
! 
! 		/*
! 		 * Copy/link the relation's primary file (segment 0 of main fork)
! 		 * to the new cluster
! 		 */
! 		unlink(new_file);
! 		transfer_relfile(pageConverter, old_file, new_file,
! 						 maps[mapnum].nspname, maps[mapnum].relname);
  
  		/* fsm/vm files added in PG 8.4 */
  		if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
--- 130,148 ----
  transfer_single_new_db(pageCnvCtx *pageConverter,
  					   FileNameMap *maps, int size)
  {
  	int			mapnum;
! 	bool		vm_crashsafe_match = true;
! 	int			segno;
! 	
  	/* 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_match = false;
  
  	for (mapnum = 0; mapnum < size; mapnum++)
  	{
! 		/* transfer primary file */
! 		transfer_relfile(pageConverter, &maps[mapnum], "");
  
  		/* fsm/vm files added in PG 8.4 */
  		if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
*************** transfer_single_new_db(pageCnvCtx *pageC
*** 187,253 ****
  			/*
  			 * Copy/link any fsm and vm files, if they exist
  			 */
! 			snprintf(file_pattern, sizeof(file_pattern), "%u_",
! 					 maps[mapnum].old_relfilenode);
! 
! 			for (fileno = 0; fileno < numFiles; fileno++)
! 			{
! 				char	   *vm_offset = strstr(namelist[fileno], "_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], file_pattern,
! 							strlen(file_pattern)) == 0 &&
! 					(!is_vm_file || !vm_crashsafe_change))
! 				{
! 					snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
! 							 namelist[fileno]);
! 					snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_dir,
! 							 maps[mapnum].new_relfilenode, strchr(namelist[fileno], '_'));
! 
! 					unlink(new_file);
! 					transfer_relfile(pageConverter, old_file, new_file,
! 								 maps[mapnum].nspname, maps[mapnum].relname);
! 				}
! 			}
  		}
  
  		/*
  		 * Now copy/link any related segments as well. Remember, PG breaks
  		 * large files into 1GB segments, the first segment has no extension,
  		 * subsequent segments are named relfilenode.1, relfilenode.2,
! 		 * relfilenode.3, ...  'fsm' and 'vm' files use underscores so are not
  		 * copied.
  		 */
! 		snprintf(file_pattern, sizeof(file_pattern), "%u.",
! 				 maps[mapnum].old_relfilenode);
! 
! 		for (fileno = 0; fileno < numFiles; fileno++)
! 		{
! 			if (strncmp(namelist[fileno], file_pattern,
! 						strlen(file_pattern)) == 0)
! 			{
! 				snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
! 						 namelist[fileno]);
! 				snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_dir,
! 						 maps[mapnum].new_relfilenode, strchr(namelist[fileno], '.'));
  
! 				unlink(new_file);
! 				transfer_relfile(pageConverter, old_file, new_file,
! 								 maps[mapnum].nspname, maps[mapnum].relname);
! 			}
  		}
  	}
- 
- 	if (numFiles > 0)
- 	{
- 		for (fileno = 0; fileno < numFiles; fileno++)
- 			pg_free(namelist[fileno]);
- 		pg_free(namelist);
- 	}
  }
  
  
--- 150,176 ----
  			/*
  			 * Copy/link any fsm and vm files, if they exist
  			 */
! 			transfer_relfile(pageConverter, &maps[mapnum], "_fsm");
! 			if (vm_crashsafe_match)
! 				transfer_relfile(pageConverter, &maps[mapnum], "_vm");
  		}
  
  		/*
  		 * Now copy/link any related segments as well. Remember, PG breaks
  		 * large files into 1GB segments, the first segment has no extension,
  		 * subsequent segments are named relfilenode.1, relfilenode.2,
! 		 * relfilenode.3.
  		 * copied.
  		 */
! 		for (segno = 1;; segno++)
!         {
!         	char suffix[65];
  
!         	snprintf(suffix, sizeof(suffix), ".%d", segno);
! 			if (transfer_relfile(pageConverter, &maps[mapnum], suffix) != 0)
! 				break;
  		}
  	}
  }
  
  
*************** transfer_single_new_db(pageCnvCtx *pageC
*** 256,266 ****
   *
   * Copy or link file from old cluster to new one.
   */
! static void
! transfer_relfile(pageCnvCtx *pageConverter, const char *old_file,
! 			  const char *new_file, const char *nspname, const char *relname)
  {
  	const char *msg;
  
  	if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
  		pg_log(PG_FATAL, "This upgrade requires page-by-page conversion, "
--- 179,213 ----
   *
   * Copy or link file from old cluster to new one.
   */
! static int
! transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
! 				 const char *suffix)
  {
  	const char *msg;
+ 	char		old_file[MAXPGPATH];
+ 	char		new_file[MAXPGPATH];
+ 	int			fd;
+ 	
+ 	snprintf(old_file, sizeof(old_file), "%s/%u%s", map->old_dir,
+ 			 map->old_relfilenode, suffix);
+ 	snprintf(new_file, sizeof(new_file), "%s/%u%s", map->new_dir,
+ 			 map->new_relfilenode, suffix);
+ 
+ 	/* file does not exist? */
+ 	if ((fd = open(old_file, O_RDONLY)) == -1)
+ 	{
+ 		if (errno == ENOENT)
+ 			return -1;
+ 		else
+ 			pg_log(PG_FATAL, "non-existant file error while copying relation \"%s.%s\" (\"%s\" to \"%s\")\n",
+ 				   map->nspname, map->relname, old_file, new_file);
+ 	}
+ 	close(fd);
+ 
+ 	unlink(new_file);
+ 
+ 	/* Copying files might take some time, so give feedback. */
+ 	pg_log(PG_REPORT, OVERWRITE_MESSAGE, old_file);
  
  	if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
  		pg_log(PG_FATAL, "This upgrade requires page-by-page conversion, "
*************** transfer_relfile(pageCnvCtx *pageConvert
*** 272,278 ****
  
  		if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
  			pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
! 				   nspname, relname, old_file, new_file, msg);
  	}
  	else
  	{
--- 219,225 ----
  
  		if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
  			pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
! 				   map->nspname, map->relname, old_file, new_file, msg);
  	}
  	else
  	{
*************** transfer_relfile(pageCnvCtx *pageConvert
*** 281,287 ****
  		if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
  			pg_log(PG_FATAL,
  				   "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
! 				   nspname, relname, old_file, new_file, msg);
  	}
! 	return;
  }
--- 228,234 ----
  		if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
  			pg_log(PG_FATAL,
  				   "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
! 				   map->nspname, map->relname, old_file, new_file, msg);
  	}
! 	return 0;
  }
