Skip to content

Commit cd08f17

Browse files
author
Commitfest Bot
committed
[CF 5728] v2 - teach pg_upgrade to handle in-place tablespaces
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5728 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/aA_6wKsPgqfbEypy@nathan Author(s): Nathan Bossart
2 parents b0635bf + 4422191 commit cd08f17

File tree

7 files changed

+143
-83
lines changed

7 files changed

+143
-83
lines changed

src/bin/pg_upgrade/check.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -946,12 +946,12 @@ check_for_new_tablespace_dir(void)
946946

947947
prep_status("Checking for new cluster tablespace directories");
948948

949-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
949+
for (tblnum = 0; tblnum < new_cluster.num_tablespaces; tblnum++)
950950
{
951951
struct stat statbuf;
952952

953953
snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
954-
os_info.old_tablespaces[tblnum],
954+
new_cluster.tablespaces[tblnum],
955955
new_cluster.tablespace_suffix);
956956

957957
if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
@@ -1003,17 +1003,17 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
10031003
* directory. We can't create a proper old cluster delete script in that
10041004
* case.
10051005
*/
1006-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1006+
for (tblnum = 0; tblnum < new_cluster.num_tablespaces; tblnum++)
10071007
{
1008-
char old_tablespace_dir[MAXPGPATH];
1008+
char new_tablespace_dir[MAXPGPATH];
10091009

1010-
strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
1011-
canonicalize_path(old_tablespace_dir);
1012-
if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
1010+
strlcpy(new_tablespace_dir, new_cluster.tablespaces[tblnum], MAXPGPATH);
1011+
canonicalize_path(new_tablespace_dir);
1012+
if (path_is_prefix_of_path(old_cluster_pgdata, new_tablespace_dir))
10131013
{
10141014
/* reproduce warning from CREATE TABLESPACE that is in the log */
10151015
pg_log(PG_WARNING,
1016-
"\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
1016+
"\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", new_tablespace_dir);
10171017

10181018
/* Unlink file in case it is left over from a previous run. */
10191019
unlink(*deletion_script_file_name);
@@ -1041,9 +1041,9 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
10411041
/* delete old cluster's alternate tablespaces */
10421042
old_tblspc_suffix = pg_strdup(old_cluster.tablespace_suffix);
10431043
fix_path_separator(old_tblspc_suffix);
1044-
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
1044+
for (tblnum = 0; tblnum < old_cluster.num_tablespaces; tblnum++)
10451045
fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1046-
fix_path_separator(os_info.old_tablespaces[tblnum]),
1046+
fix_path_separator(old_cluster.tablespaces[tblnum]),
10471047
old_tblspc_suffix, PATH_QUOTE);
10481048
pfree(old_tblspc_suffix);
10491049

src/bin/pg_upgrade/info.c

+32-4
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+
PQgetvalue(res, relnum, i_spclocation));
646+
else
647+
tablespace = PQgetvalue(res, relnum, i_spclocation);
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

+7-4
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

+4-4
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
} ClusterInfo;
@@ -354,8 +356,6 @@ typedef struct
354356
const char *progname; /* complete pathname for this program */
355357
char *user; /* username for clusters */
356358
bool user_specified; /* user specified on command-line */
357-
char **old_tablespaces; /* tablespaces */
358-
int num_old_tablespaces;
359359
LibraryInfo *libraries; /* loadable libraries */
360360
int num_libraries;
361361
ClusterInfo *running_cluster;
@@ -455,7 +455,7 @@ void transfer_all_new_tablespaces(DbInfoArr *old_db_arr,
455455
DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata);
456456
void transfer_all_new_dbs(DbInfoArr *old_db_arr,
457457
DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata,
458-
char *old_tablespace);
458+
char *old_tablespace, char *new_tablespace);
459459

460460
/* tablespace.c */
461461

@@ -503,7 +503,7 @@ void parallel_exec_prog(const char *log_file, const char *opt_log_file,
503503
const char *fmt,...) pg_attribute_printf(3, 4);
504504
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
505505
char *old_pgdata, char *new_pgdata,
506-
char *old_tablespace);
506+
char *old_tablespace, char *new_tablespace);
507507
bool reap_child(bool wait_for_child);
508508

509509
/* task.c */

src/bin/pg_upgrade/relfilenumber.c

+26-31
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)