diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
new file mode 100644
index f04707f..acf8660
*** a/contrib/pg_upgrade/check.c
--- b/contrib/pg_upgrade/check.c
*************** create_script_for_old_cluster_deletion(c
*** 707,726 ****
  			fprintf(script, "\n");
  			/* remove PG_VERSION? */
  			if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
! 				fprintf(script, RM_CMD " %s%s%cPG_VERSION\n",
  						fix_path_separator(os_info.old_tablespaces[tblnum]),
- 						fix_path_separator(old_cluster.tablespace_suffix),
  						PATH_SEPARATOR);
  
  			for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
! 			{
! 				fprintf(script, RMDIR_CMD " %s%s%c%d\n",
  						fix_path_separator(os_info.old_tablespaces[tblnum]),
- 						fix_path_separator(old_cluster.tablespace_suffix),
  						PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid);
- 			}
  		}
  		else
  
  			/*
  			 * Simply delete the tablespace directory, which might be ".old"
--- 707,724 ----
  			fprintf(script, "\n");
  			/* remove PG_VERSION? */
  			if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
! 				fprintf(script, RM_CMD " %s%cPG_VERSION\n",
  						fix_path_separator(os_info.old_tablespaces[tblnum]),
  						PATH_SEPARATOR);
  
  			for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
! 				fprintf(script, RMDIR_CMD " %s%c%d\n",
  						fix_path_separator(os_info.old_tablespaces[tblnum]),
  						PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid);
  		}
  		else
+ 		{
+ 			char	*suffix_path = pg_strdup(old_cluster.tablespace_suffix);
  
  			/*
  			 * Simply delete the tablespace directory, which might be ".old"
*************** create_script_for_old_cluster_deletion(c
*** 728,734 ****
  			 */
  			fprintf(script, RMDIR_CMD " %s%s\n",
  					fix_path_separator(os_info.old_tablespaces[tblnum]),
! 					fix_path_separator(old_cluster.tablespace_suffix));
  	}
  
  	fclose(script);
--- 726,734 ----
  			 */
  			fprintf(script, RMDIR_CMD " %s%s\n",
  					fix_path_separator(os_info.old_tablespaces[tblnum]),
! 					fix_path_separator(suffix_path));
! 			pfree(suffix_path);
! 		}
  	}
  
  	fclose(script);
diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
new file mode 100644
index 3d0dd1a..fd083de
*** a/contrib/pg_upgrade/info.c
--- b/contrib/pg_upgrade/info.c
*************** create_rel_filename_map(const char *old_
*** 108,127 ****
  		 * relation belongs to the default tablespace, hence relfiles should
  		 * exist in the data directories.
  		 */
! 		strlcpy(map->old_tablespace, old_data, sizeof(map->old_tablespace));
! 		strlcpy(map->new_tablespace, new_data, sizeof(map->new_tablespace));
! 		strlcpy(map->old_tablespace_suffix, "/base", sizeof(map->old_tablespace_suffix));
! 		strlcpy(map->new_tablespace_suffix, "/base", sizeof(map->new_tablespace_suffix));
  	}
  	else
  	{
  		/* relation belongs to a tablespace, so use the tablespace location */
! 		strlcpy(map->old_tablespace, old_rel->tablespace, sizeof(map->old_tablespace));
! 		strlcpy(map->new_tablespace, new_rel->tablespace, sizeof(map->new_tablespace));
! 		strlcpy(map->old_tablespace_suffix, old_cluster.tablespace_suffix,
! 				sizeof(map->old_tablespace_suffix));
! 		strlcpy(map->new_tablespace_suffix, new_cluster.tablespace_suffix,
! 				sizeof(map->new_tablespace_suffix));
  	}
  
  	map->old_db_oid = old_db->db_oid;
--- 108,125 ----
  		 * relation belongs to the default tablespace, hence relfiles should
  		 * exist in the data directories.
  		 */
! 		map->old_tablespace = old_data;
! 		map->new_tablespace = new_data;
! 		map->old_tablespace_suffix = "/base";
! 		map->new_tablespace_suffix = "/base";
  	}
  	else
  	{
  		/* relation belongs to a tablespace, so use the tablespace location */
! 		map->old_tablespace = old_rel->tablespace;
! 		map->new_tablespace = new_rel->tablespace;
! 		map->old_tablespace_suffix = old_cluster.tablespace_suffix;
! 		map->new_tablespace_suffix = new_cluster.tablespace_suffix;
  	}
  
  	map->old_db_oid = old_db->db_oid;
*************** get_db_infos(ClusterInfo *cluster)
*** 231,237 ****
  	{
  		dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
  		dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
! 		snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s",
  				 PQgetvalue(res, tupnum, i_spclocation));
  	}
  	PQclear(res);
--- 229,235 ----
  	{
  		dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
  		dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
! 		snprintf(dbinfos[tupnum].db_tablespace, sizeof(dbinfos[tupnum].db_tablespace), "%s",
  				 PQgetvalue(res, tupnum, i_spclocation));
  	}
  	PQclear(res);
*************** get_rel_infos(ClusterInfo *cluster, DbIn
*** 264,269 ****
--- 262,268 ----
  	int			num_rels = 0;
  	char	   *nspname = NULL;
  	char	   *relname = NULL;
+ 	char	   *tablespace = NULL;
  	int			i_spclocation,
  				i_nspname,
  				i_relname,
*************** get_rel_infos(ClusterInfo *cluster, DbIn
*** 271,276 ****
--- 270,276 ----
  				i_relfilenode,
  				i_reltablespace;
  	char		query[QUERY_ALLOC];
+ 	char	   *last_namespace = NULL, *last_tablespace = NULL;
  
  	/*
  	 * pg_largeobject contains user data that does not appear in pg_dumpall
*************** get_rel_infos(ClusterInfo *cluster, DbIn
*** 366,391 ****
  	for (relnum = 0; relnum < ntups; relnum++)
  	{
  		RelInfo    *curr = &relinfos[num_rels++];
- 		const char *tblspace;
  
  		curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
  
  		nspname = PQgetvalue(res, relnum, i_nspname);
! 		curr->nspname = pg_strdup(nspname);
  
  		relname = PQgetvalue(res, relnum, i_relname);
  		curr->relname = pg_strdup(relname);
  
  		curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
  
  		if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
! 			/* Might be "", meaning the cluster default location. */
! 			tblspace = PQgetvalue(res, relnum, i_spclocation);
! 		else
! 			/* A zero reltablespace indicates the database tablespace. */
! 			tblspace = dbinfo->db_tblspace;
  
! 		strlcpy(curr->tablespace, tblspace, sizeof(curr->tablespace));
  	}
  	PQclear(res);
  
--- 366,418 ----
  	for (relnum = 0; relnum < ntups; relnum++)
  	{
  		RelInfo    *curr = &relinfos[num_rels++];
  
  		curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
  
  		nspname = PQgetvalue(res, relnum, i_nspname);
! 		curr->nsp_alloc = false;
! 
! 		/*
! 		 * Many of the namespace and tablespace strings are identical,
! 		 * so we try to reuse the allocated string pointers where possible
! 		 * to reduce memory consumption.
! 		 */
! 		/* Can we reuse the previous string allocation? */
! 		if (last_namespace && strcmp(nspname, last_namespace) == 0)
! 			curr->nspname = last_namespace;
! 		else
! 		{
! 			last_namespace = curr->nspname = pg_strdup(nspname);
! 			curr->nsp_alloc = true;
! 		}
  
  		relname = PQgetvalue(res, relnum, i_relname);
  		curr->relname = pg_strdup(relname);
  
  		curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
+ 		curr->tblsp_alloc = false;
  
+ 		/* Is the tablespace oid non-zero? */
  		if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
! 		{
! 			/*
! 			 * The tablespace location might be "", meaning the cluster
! 			 * default location, i.e. pg_default or pg_global.
! 			 */
! 			tablespace = PQgetvalue(res, relnum, i_spclocation);
  
! 			/* Can we reuse the previous string allocation? */
! 			if (last_tablespace && strcmp(tablespace, last_tablespace) == 0)
! 				curr->tablespace = last_tablespace;
! 			else
! 			{
! 				last_tablespace = curr->tablespace = pg_strdup(tablespace);
! 				curr->tblsp_alloc = true;
! 			}
! 		}
! 		else
! 			/* A zero reltablespace oid indicates the database tablespace. */
! 			curr->tablespace = dbinfo->db_tablespace;
  	}
  	PQclear(res);
  
*************** free_rel_infos(RelInfoArr *rel_arr)
*** 419,426 ****
  
  	for (relnum = 0; relnum < rel_arr->nrels; relnum++)
  	{
! 		pg_free(rel_arr->rels[relnum].nspname);
  		pg_free(rel_arr->rels[relnum].relname);
  	}
  	pg_free(rel_arr->rels);
  	rel_arr->nrels = 0;
--- 446,456 ----
  
  	for (relnum = 0; relnum < rel_arr->nrels; relnum++)
  	{
! 		if (rel_arr->rels[relnum].nsp_alloc)
! 			pg_free(rel_arr->rels[relnum].nspname);
  		pg_free(rel_arr->rels[relnum].relname);
+ 		if (rel_arr->rels[relnum].tblsp_alloc)
+ 			pg_free(rel_arr->rels[relnum].tablespace);
  	}
  	pg_free(rel_arr->rels);
  	rel_arr->nrels = 0;
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
new file mode 100644
index de487bc..389ec93
*** a/contrib/pg_upgrade/pg_upgrade.h
--- b/contrib/pg_upgrade/pg_upgrade.h
*************** typedef struct
*** 127,133 ****
  	Oid			reloid;			/* relation oid */
  	Oid			relfilenode;	/* relation relfile node */
  	/* relation tablespace path, or "" for the cluster default */
! 	char		tablespace[MAXPGPATH];
  } RelInfo;
  
  typedef struct
--- 127,135 ----
  	Oid			reloid;			/* relation oid */
  	Oid			relfilenode;	/* relation relfile node */
  	/* relation tablespace path, or "" for the cluster default */
! 	char	   *tablespace;
! 	bool		nsp_alloc;
! 	bool		tblsp_alloc;
  } RelInfo;
  
  typedef struct
*************** typedef struct
*** 141,150 ****
   */
  typedef struct
  {
! 	char		old_tablespace[MAXPGPATH];
! 	char		new_tablespace[MAXPGPATH];
! 	char		old_tablespace_suffix[MAXPGPATH];
! 	char		new_tablespace_suffix[MAXPGPATH];
  	Oid			old_db_oid;
  	Oid			new_db_oid;
  
--- 143,152 ----
   */
  typedef struct
  {
! 	const char		*old_tablespace;
! 	const char		*new_tablespace;
! 	const char		*old_tablespace_suffix;
! 	const char		*new_tablespace_suffix;
  	Oid			old_db_oid;
  	Oid			new_db_oid;
  
*************** typedef struct
*** 166,172 ****
  {
  	Oid			db_oid;			/* oid of the database */
  	char	   *db_name;		/* database name */
! 	char		db_tblspace[MAXPGPATH]; /* database default tablespace path */
  	RelInfoArr	rel_arr;		/* array of all user relinfos */
  } DbInfo;
  
--- 168,174 ----
  {
  	Oid			db_oid;			/* oid of the database */
  	char	   *db_name;		/* database name */
! 	char		db_tablespace[MAXPGPATH]; /* database default tablespace path */
  	RelInfoArr	rel_arr;		/* array of all user relinfos */
  } DbInfo;
  
*************** typedef struct
*** 256,262 ****
  	Oid			pg_database_oid;	/* OID of pg_database relation */
  	Oid			install_role_oid;		/* OID of connected role */
  	Oid			role_count;		/* number of roles defined in the cluster */
! 	char	   *tablespace_suffix;		/* directory specification */
  } ClusterInfo;
  
  
--- 258,264 ----
  	Oid			pg_database_oid;	/* OID of pg_database relation */
  	Oid			install_role_oid;		/* OID of connected role */
  	Oid			role_count;		/* number of roles defined in the cluster */
! 	const char *tablespace_suffix;		/* directory specification */
  } ClusterInfo;
  
  
