Skip to content

Commit 1cc337c

Browse files
nathan-bossartCommitfest Bot
authored andcommitted
Teach pg_upgrade to handle in-place tablespaces.
Presently, pg_upgrade assumes that all non-default tablespaces don't move to different directories during upgrade. Unfortunately, this isn't true for in-place tablespaces, which move to the new cluster's pg_tblspc directory. This commit teaches pg_upgrade to handle in-place tablespaces by retrieving the tablespace directories for both the old and new clusters. In turn, we can relax the prohibition on non-default tablespaces for same-version upgrades, i.e., if all non-default tablespaces are in-place, pg_upgrade may proceed. This change is primarily intended to enable additional pg_upgrade testing with non-default tablespaces, as is done in 006_transfer_modes.pl.
1 parent 15d33eb commit 1cc337c

File tree

7 files changed

+162
-70
lines changed

7 files changed

+162
-70
lines changed

src/bin/pg_upgrade/check.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -956,12 +956,12 @@ check_for_new_tablespace_dir(void)
956956

957957
prep_status("Checking for new cluster tablespace directories");
958958

959-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
959+
for (tblnum = 0; tblnum < new_cluster.num_tablespaces; tblnum++)
960960
{
961961
struct stat statbuf;
962962

963963
snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
964-
os_info.old_tablespaces[tblnum],
964+
new_cluster.tablespaces[tblnum],
965965
new_cluster.tablespace_suffix);
966966

967967
if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
@@ -1013,17 +1013,17 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
10131013
* directory. We can't create a proper old cluster delete script in that
10141014
* case.
10151015
*/
1016-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1016+
for (tblnum = 0; tblnum < new_cluster.num_tablespaces; tblnum++)
10171017
{
1018-
char old_tablespace_dir[MAXPGPATH];
1018+
char new_tablespace_dir[MAXPGPATH];
10191019

1020-
strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
1021-
canonicalize_path(old_tablespace_dir);
1022-
if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
1020+
strlcpy(new_tablespace_dir, new_cluster.tablespaces[tblnum], MAXPGPATH);
1021+
canonicalize_path(new_tablespace_dir);
1022+
if (path_is_prefix_of_path(old_cluster_pgdata, new_tablespace_dir))
10231023
{
10241024
/* reproduce warning from CREATE TABLESPACE that is in the log */
10251025
pg_log(PG_WARNING,
1026-
"\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
1026+
"\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", new_tablespace_dir);
10271027

10281028
/* Unlink file in case it is left over from a previous run. */
10291029
unlink(*deletion_script_file_name);
@@ -1051,9 +1051,9 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
10511051
/* delete old cluster's alternate tablespaces */
10521052
old_tblspc_suffix = pg_strdup(old_cluster.tablespace_suffix);
10531053
fix_path_separator(old_tblspc_suffix);
1054-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1054+
for (tblnum = 0; tblnum < old_cluster.num_tablespaces; tblnum++)
10551055
fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1056-
fix_path_separator(os_info.old_tablespaces[tblnum]),
1056+
fix_path_separator(old_cluster.tablespaces[tblnum]),
10571057
old_tblspc_suffix, PATH_QUOTE);
10581058
pfree(old_tblspc_suffix);
10591059

src/bin/pg_upgrade/info.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,24 @@ get_db_infos(ClusterInfo *cluster)
443443

444444
for (tupnum = 0; tupnum < ntups; tupnum++)
445445
{
446+
char *spcloc = PQgetvalue(res, tupnum, i_spclocation);
447+
bool inplace = spcloc[0] && !is_absolute_path(spcloc);
448+
446449
dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
447450
dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
448-
snprintf(dbinfos[tupnum].db_tablespace, sizeof(dbinfos[tupnum].db_tablespace), "%s",
449-
PQgetvalue(res, tupnum, i_spclocation));
451+
452+
/*
453+
* For in-place tablespaces, pg_tablespace_location() returns a path
454+
* relative to the data directory.
455+
*/
456+
if (inplace)
457+
snprintf(dbinfos[tupnum].db_tablespace,
458+
sizeof(dbinfos[tupnum].db_tablespace),
459+
"%s/%s", cluster->pgdata, spcloc);
460+
else
461+
snprintf(dbinfos[tupnum].db_tablespace,
462+
sizeof(dbinfos[tupnum].db_tablespace),
463+
"%s", spcloc);
450464
}
451465
PQclear(res);
452466

@@ -616,11 +630,21 @@ process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg)
616630
/* Is the tablespace oid non-default? */
617631
if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
618632
{
633+
char *spcloc = PQgetvalue(res, relnum, i_spclocation);
634+
bool inplace = spcloc[0] && !is_absolute_path(spcloc);
635+
619636
/*
620637
* The tablespace location might be "", meaning the cluster
621-
* default location, i.e. pg_default or pg_global.
638+
* default location, i.e. pg_default or pg_global. For in-place
639+
* tablespaces, pg_tablespace_location() returns a path relative
640+
* to the data directory.
622641
*/
623-
tablespace = PQgetvalue(res, relnum, i_spclocation);
642+
if (inplace)
643+
tablespace = psprintf("%s/%s",
644+
os_info.running_cluster->pgdata,
645+
spcloc);
646+
else
647+
tablespace = spcloc;
624648

625649
/* Can we reuse the previous string allocation? */
626650
if (last_tablespace && strcmp(tablespace, last_tablespace) == 0)
@@ -630,6 +654,10 @@ process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg)
630654
last_tablespace = curr->tablespace = pg_strdup(tablespace);
631655
curr->tblsp_alloc = true;
632656
}
657+
658+
/* Free palloc'd string for in-place tablespaces. */
659+
if (inplace)
660+
pfree(tablespace);
633661
}
634662
else
635663
/* A zero reltablespace oid indicates the database tablespace. */

src/bin/pg_upgrade/parallel.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct
4040
char *old_pgdata;
4141
char *new_pgdata;
4242
char *old_tablespace;
43+
char *new_tablespace;
4344
} transfer_thread_arg;
4445

4546
static exec_thread_arg **exec_thread_args;
@@ -171,7 +172,7 @@ win32_exec_prog(exec_thread_arg *args)
171172
void
172173
parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
173174
char *old_pgdata, char *new_pgdata,
174-
char *old_tablespace)
175+
char *old_tablespace, char *new_tablespace)
175176
{
176177
#ifndef WIN32
177178
pid_t child;
@@ -181,7 +182,7 @@ parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
181182
#endif
182183

183184
if (user_opts.jobs <= 1)
184-
transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata, NULL);
185+
transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata, NULL, NULL);
185186
else
186187
{
187188
/* parallel */
@@ -225,7 +226,7 @@ parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
225226
if (child == 0)
226227
{
227228
transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata,
228-
old_tablespace);
229+
old_tablespace, new_tablespace);
229230
/* if we take another exit path, it will be non-zero */
230231
/* use _exit to skip atexit() functions */
231232
_exit(0);
@@ -246,6 +247,7 @@ parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
246247
new_arg->new_pgdata = pg_strdup(new_pgdata);
247248
pg_free(new_arg->old_tablespace);
248249
new_arg->old_tablespace = old_tablespace ? pg_strdup(old_tablespace) : NULL;
250+
new_arg->new_tablespace = new_tablespace ? pg_strdup(new_tablespace) : NULL;
249251

250252
child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_transfer_all_new_dbs,
251253
new_arg, 0, NULL);
@@ -263,7 +265,8 @@ DWORD
263265
win32_transfer_all_new_dbs(transfer_thread_arg *args)
264266
{
265267
transfer_all_new_dbs(args->old_db_arr, args->new_db_arr, args->old_pgdata,
266-
args->new_pgdata, args->old_tablespace);
268+
args->new_pgdata, args->old_tablespace,
269+
args->new_tablespace);
267270

268271
/* terminates thread */
269272
return 0;

src/bin/pg_upgrade/pg_upgrade.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ typedef struct
300300
uint32 major_version; /* PG_VERSION of cluster */
301301
char major_version_str[64]; /* string PG_VERSION of cluster */
302302
uint32 bin_version; /* version returned from pg_ctl */
303+
char **tablespaces; /* tablespace directories */
304+
int num_tablespaces;
303305
const char *tablespace_suffix; /* directory specification */
304306
int nsubs; /* number of subscriptions */
305307
bool sub_retain_dead_tuples; /* whether a subscription enables
@@ -356,8 +358,6 @@ typedef struct
356358
const char *progname; /* complete pathname for this program */
357359
char *user; /* username for clusters */
358360
bool user_specified; /* user specified on command-line */
359-
char **old_tablespaces; /* tablespaces */
360-
int num_old_tablespaces;
361361
LibraryInfo *libraries; /* loadable libraries */
362362
int num_libraries;
363363
ClusterInfo *running_cluster;
@@ -457,7 +457,7 @@ void transfer_all_new_tablespaces(DbInfoArr *old_db_arr,
457457
DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata);
458458
void transfer_all_new_dbs(DbInfoArr *old_db_arr,
459459
DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata,
460-
char *old_tablespace);
460+
char *old_tablespace, char *new_tablespace);
461461

462462
/* tablespace.c */
463463

@@ -505,7 +505,7 @@ void parallel_exec_prog(const char *log_file, const char *opt_log_file,
505505
const char *fmt,...) pg_attribute_printf(3, 4);
506506
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
507507
char *old_pgdata, char *new_pgdata,
508-
char *old_tablespace);
508+
char *old_tablespace, char *new_tablespace);
509509
bool reap_child(bool wait_for_child);
510510

511511
/* task.c */

src/bin/pg_upgrade/relfilenumber.c

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "common/logging.h"
1818
#include "pg_upgrade.h"
1919

20-
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace);
20+
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace);
2121
static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit);
2222

2323
/*
@@ -136,21 +136,22 @@ transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
136136
*/
137137
if (user_opts.jobs <= 1)
138138
parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
139-
new_pgdata, NULL);
139+
new_pgdata, NULL, NULL);
140140
else
141141
{
142142
int tblnum;
143143

144144
/* transfer default tablespace */
145145
parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
146-
new_pgdata, old_pgdata);
146+
new_pgdata, old_pgdata, new_pgdata);
147147

148-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
148+
for (tblnum = 0; tblnum < old_cluster.num_tablespaces; tblnum++)
149149
parallel_transfer_all_new_dbs(old_db_arr,
150150
new_db_arr,
151151
old_pgdata,
152152
new_pgdata,
153-
os_info.old_tablespaces[tblnum]);
153+
old_cluster.tablespaces[tblnum],
154+
new_cluster.tablespaces[tblnum]);
154155
/* reap all children */
155156
while (reap_child(true) == true)
156157
;
@@ -169,7 +170,8 @@ transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
169170
*/
170171
void
171172
transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
172-
char *old_pgdata, char *new_pgdata, char *old_tablespace)
173+
char *old_pgdata, char *new_pgdata,
174+
char *old_tablespace, char *new_tablespace)
173175
{
174176
int old_dbnum,
175177
new_dbnum;
@@ -204,7 +206,7 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
204206
new_pgdata);
205207
if (n_maps)
206208
{
207-
transfer_single_new_db(mappings, n_maps, old_tablespace);
209+
transfer_single_new_db(mappings, n_maps, old_tablespace, new_tablespace);
208210
}
209211
/* We allocate something even for n_maps == 0 */
210212
pg_free(mappings);
@@ -234,10 +236,10 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
234236
* moved_db_dir: Destination for the pg_restore-generated database directory.
235237
*/
236238
static bool
237-
prepare_for_swap(const char *old_tablespace, Oid db_oid,
238-
char *old_catalog_dir, char *new_db_dir, char *moved_db_dir)
239+
prepare_for_swap(const char *old_tablespace, const char *new_tablespace,
240+
Oid db_oid, char *old_catalog_dir, char *new_db_dir,
241+
char *moved_db_dir)
239242
{
240-
const char *new_tablespace;
241243
const char *old_tblspc_suffix;
242244
const char *new_tblspc_suffix;
243245
char old_tblspc[MAXPGPATH];
@@ -247,24 +249,14 @@ prepare_for_swap(const char *old_tablespace, Oid db_oid,
247249
struct stat st;
248250

249251
if (strcmp(old_tablespace, old_cluster.pgdata) == 0)
250-
{
251-
new_tablespace = new_cluster.pgdata;
252-
new_tblspc_suffix = "/base";
253252
old_tblspc_suffix = "/base";
254-
}
255253
else
256-
{
257-
/*
258-
* XXX: The below line is a hack to deal with the fact that we
259-
* presently don't have an easy way to find the corresponding new
260-
* tablespace's path. This will need to be fixed if/when we add
261-
* pg_upgrade support for in-place tablespaces.
262-
*/
263-
new_tablespace = old_tablespace;
254+
old_tblspc_suffix = old_cluster.tablespace_suffix;
264255

256+
if (strcmp(new_tablespace, new_cluster.pgdata) == 0)
257+
new_tblspc_suffix = "/base";
258+
else
265259
new_tblspc_suffix = new_cluster.tablespace_suffix;
266-
old_tblspc_suffix = old_cluster.tablespace_suffix;
267-
}
268260

269261
/* Old and new cluster paths. */
270262
snprintf(old_tblspc, sizeof(old_tblspc), "%s%s", old_tablespace, old_tblspc_suffix);
@@ -450,7 +442,7 @@ swap_catalog_files(FileNameMap *maps, int size, const char *old_catalog_dir,
450442
* during pg_restore.
451443
*/
452444
static void
453-
do_swap(FileNameMap *maps, int size, char *old_tablespace)
445+
do_swap(FileNameMap *maps, int size, char *old_tablespace, char *new_tablespace)
454446
{
455447
char old_catalog_dir[MAXPGPATH];
456448
char new_db_dir[MAXPGPATH];
@@ -470,21 +462,23 @@ do_swap(FileNameMap *maps, int size, char *old_tablespace)
470462
*/
471463
if (old_tablespace)
472464
{
473-
if (prepare_for_swap(old_tablespace, maps[0].db_oid,
465+
if (prepare_for_swap(old_tablespace, new_tablespace, maps[0].db_oid,
474466
old_catalog_dir, new_db_dir, moved_db_dir))
475467
swap_catalog_files(maps, size,
476468
old_catalog_dir, new_db_dir, moved_db_dir);
477469
}
478470
else
479471
{
480-
if (prepare_for_swap(old_cluster.pgdata, maps[0].db_oid,
472+
if (prepare_for_swap(old_cluster.pgdata, new_cluster.pgdata, maps[0].db_oid,
481473
old_catalog_dir, new_db_dir, moved_db_dir))
482474
swap_catalog_files(maps, size,
483475
old_catalog_dir, new_db_dir, moved_db_dir);
484476

485-
for (int tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
477+
for (int tblnum = 0; tblnum < old_cluster.num_tablespaces; tblnum++)
486478
{
487-
if (prepare_for_swap(os_info.old_tablespaces[tblnum], maps[0].db_oid,
479+
if (prepare_for_swap(old_cluster.tablespaces[tblnum],
480+
new_cluster.tablespaces[tblnum],
481+
maps[0].db_oid,
488482
old_catalog_dir, new_db_dir, moved_db_dir))
489483
swap_catalog_files(maps, size,
490484
old_catalog_dir, new_db_dir, moved_db_dir);
@@ -498,7 +492,8 @@ do_swap(FileNameMap *maps, int size, char *old_tablespace)
498492
* create links for mappings stored in "maps" array.
499493
*/
500494
static void
501-
transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
495+
transfer_single_new_db(FileNameMap *maps, int size,
496+
char *old_tablespace, char *new_tablespace)
502497
{
503498
int mapnum;
504499
bool vm_must_add_frozenbit = false;
@@ -520,7 +515,7 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
520515
*/
521516
Assert(!vm_must_add_frozenbit);
522517

523-
do_swap(maps, size, old_tablespace);
518+
do_swap(maps, size, old_tablespace, new_tablespace);
524519
return;
525520
}
526521

0 commit comments

Comments
 (0)