Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 16e7a8f

Browse files
committed
Allow "in place" tablespaces.
This is a backpatch to branches 10-14 of the following commits: 7170f21 Allow "in place" tablespaces. c6f2f01 Fix pg_basebackup with in-place tablespaces. f6f0db4 Fix pg_tablespace_location() with in-place tablespaces 7a7cd84 doc: Remove mention to in-place tablespaces for pg_tablespace_location() 5344723 Remove unnecessary Windows-specific basebackup code. In-place tablespaces were introduced as a testing helper mechanism, but they are going to be used for a bugfix in WAL replay to be backpatched to all stable branches. I (Álvaro) had to adjust some code to account for lack of get_dirent_type() in branches prior to 14. Author: Thomas Munro <thomas.munro@gmail.com> Author: Michaël Paquier <michael@paquier.xyz> Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/20220722081858.omhn2in5zt3g4nek@alvherre.pgsql
1 parent 6c193c2 commit 16e7a8f

File tree

6 files changed

+114
-7
lines changed

6 files changed

+114
-7
lines changed

doc/src/sgml/config.sgml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9949,6 +9949,25 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
99499949
</para>
99509950

99519951
<variablelist>
9952+
<varlistentry id="guc-allow-in-place-tablespaces" xreflabel="allow_in_place_tablespaces">
9953+
<term><varname>allow_in_place_tablespaces</varname> (<type>boolean</type>)
9954+
<indexterm>
9955+
<primary><varname>allow_in_place_tablespaces</varname> configuration parameter</primary>
9956+
</indexterm>
9957+
</term>
9958+
<listitem>
9959+
<para>
9960+
Allows tablespaces to be created as directories inside
9961+
<filename>pg_tblspc</filename>, when an empty location string
9962+
is provided to the <command>CREATE TABLESPACE</command> command. This
9963+
is intended to allow testing replication scenarios where primary and
9964+
standby servers are running on the same machine. Such directories
9965+
are likely to confuse backup tools that expect to find only symbolic
9966+
links in that location. Only superusers can change this setting.
9967+
</para>
9968+
</listitem>
9969+
</varlistentry>
9970+
99529971
<varlistentry id="guc-allow-system-table-mods" xreflabel="allow_system_table_mods">
99539972
<term><varname>allow_system_table_mods</varname> (<type>boolean</type>)
99549973
<indexterm>

src/backend/access/transam/xlog.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10925,13 +10925,33 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
1092510925
int rllen;
1092610926
StringInfoData buflinkpath;
1092710927
char *s = linkpath;
10928+
#ifndef WIN32
10929+
struct stat st;
10930+
#endif
1092810931

1092910932
/* Skip special stuff */
1093010933
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
1093110934
continue;
1093210935

1093310936
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
1093410937

10938+
/*
10939+
* Skip anything that isn't a symlink/junction. For testing only,
10940+
* we sometimes use allow_in_place_tablespaces to create
10941+
* directories directly under pg_tblspc, which would fail below.
10942+
*/
10943+
#ifndef WIN32
10944+
if (lstat(fullpath, &st) < 0)
10945+
ereport(LOG,
10946+
(errcode_for_file_access(),
10947+
errmsg("could not stat file \"%s\": %m",
10948+
fullpath)));
10949+
else if (!S_ISLNK(st.st_mode))
10950+
#else /* WIN32 */
10951+
if (!pgwin32_is_junction(fullpath))
10952+
#endif
10953+
continue;
10954+
1093510955
#if defined(HAVE_READLINK) || defined(WIN32)
1093610956
rllen = readlink(fullpath, linkpath, sizeof(linkpath));
1093710957
if (rllen < 0)

src/backend/commands/tablespace.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
/* GUC variables */
8888
char *default_tablespace = NULL;
8989
char *temp_tablespaces = NULL;
90+
bool allow_in_place_tablespaces = false;
9091

9192

9293
static void create_tablespace_directories(const char *location,
@@ -241,6 +242,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
241242
char *location;
242243
Oid ownerId;
243244
Datum newOptions;
245+
bool in_place;
244246

245247
/* Must be super user */
246248
if (!superuser())
@@ -266,12 +268,15 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
266268
(errcode(ERRCODE_INVALID_NAME),
267269
errmsg("tablespace location cannot contain single quotes")));
268270

271+
in_place = allow_in_place_tablespaces && strlen(location) == 0;
272+
269273
/*
270274
* Allowing relative paths seems risky
271275
*
272-
* this also helps us ensure that location is not empty or whitespace
276+
* This also helps us ensure that location is not empty or whitespace,
277+
* unless specifying a developer-only in-place tablespace.
273278
*/
274-
if (!is_absolute_path(location))
279+
if (!in_place && !is_absolute_path(location))
275280
ereport(ERROR,
276281
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277282
errmsg("tablespace location must be an absolute path")));
@@ -592,16 +597,36 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
592597
char *linkloc;
593598
char *location_with_version_dir;
594599
struct stat st;
600+
bool in_place;
595601

596602
linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
597-
location_with_version_dir = psprintf("%s/%s", location,
603+
604+
/*
605+
* If we're asked to make an 'in place' tablespace, create the directory
606+
* directly where the symlink would normally go. This is a developer-only
607+
* option for now, to facilitate regression testing.
608+
*/
609+
in_place = strlen(location) == 0;
610+
611+
if (in_place)
612+
{
613+
if (MakePGDirectory(linkloc) < 0 && errno != EEXIST)
614+
ereport(ERROR,
615+
(errcode_for_file_access(),
616+
errmsg("could not create directory \"%s\": %m",
617+
linkloc)));
618+
}
619+
620+
location_with_version_dir = psprintf("%s/%s", in_place ? linkloc : location,
598621
TABLESPACE_VERSION_DIRECTORY);
599622

600623
/*
601624
* Attempt to coerce target directory to safe permissions. If this fails,
602-
* it doesn't exist or has the wrong owner.
625+
* it doesn't exist or has the wrong owner. Not needed for in-place mode,
626+
* because in that case we created the directory with the desired
627+
* permissions.
603628
*/
604-
if (chmod(location, pg_dir_create_mode) != 0)
629+
if (!in_place && chmod(location, pg_dir_create_mode) != 0)
605630
{
606631
if (errno == ENOENT)
607632
ereport(ERROR,
@@ -650,13 +675,13 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
650675
/*
651676
* In recovery, remove old symlink, in case it points to the wrong place.
652677
*/
653-
if (InRecovery)
678+
if (!in_place && InRecovery)
654679
remove_tablespace_symlink(linkloc);
655680

656681
/*
657682
* Create the symlink under PGDATA
658683
*/
659-
if (symlink(location, linkloc) < 0)
684+
if (!in_place && symlink(location, linkloc) < 0)
660685
ereport(ERROR,
661686
(errcode_for_file_access(),
662687
errmsg("could not create symbolic link \"%s\": %m",

src/backend/utils/adt/misc.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "postgres.h"
1616

1717
#include <sys/file.h>
18+
#include <sys/stat.h>
1819
#include <dirent.h>
1920
#include <fcntl.h>
2021
#include <math.h>
@@ -306,6 +307,9 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
306307
char sourcepath[MAXPGPATH];
307308
char targetpath[MAXPGPATH];
308309
int rllen;
310+
#ifndef WIN32
311+
struct stat st;
312+
#endif
309313

310314
/*
311315
* It's useful to apply this function to pg_class.reltablespace, wherein
@@ -330,6 +334,31 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
330334
*/
331335
snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
332336

337+
/*
338+
* Before reading the link, check if the source path is a link or a
339+
* junction point. Note that a directory is possible for a tablespace
340+
* created with allow_in_place_tablespaces enabled. If a directory is
341+
* found, a relative path to the data directory is returned.
342+
*/
343+
#ifdef WIN32
344+
if (!pgwin32_is_junction(sourcepath))
345+
PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
346+
#else
347+
if (lstat(sourcepath, &st) < 0)
348+
{
349+
ereport(ERROR,
350+
(errcode_for_file_access(),
351+
errmsg("could not stat file \"%s\": %m",
352+
sourcepath)));
353+
}
354+
355+
if (!S_ISLNK(st.st_mode))
356+
PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
357+
#endif
358+
359+
/*
360+
* In presence of a link or a junction point, return the path pointing to.
361+
*/
333362
rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
334363
if (rllen < 0)
335364
ereport(ERROR,

src/backend/utils/misc/guc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "catalog/storage.h"
4040
#include "commands/async.h"
4141
#include "commands/prepare.h"
42+
#include "commands/tablespace.h"
4243
#include "commands/trigger.h"
4344
#include "commands/user.h"
4445
#include "commands/vacuum.h"
@@ -1871,6 +1872,17 @@ static struct config_bool ConfigureNamesBool[] =
18711872
NULL, NULL, NULL
18721873
},
18731874

1875+
{
1876+
{"allow_in_place_tablespaces", PGC_SUSET, DEVELOPER_OPTIONS,
1877+
gettext_noop("Allows tablespaces directly inside pg_tblspc, for testing."),
1878+
NULL,
1879+
GUC_NOT_IN_SAMPLE
1880+
},
1881+
&allow_in_place_tablespaces,
1882+
false,
1883+
NULL, NULL, NULL
1884+
},
1885+
18741886
{
18751887
{"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
18761888
gettext_noop("Enables backward compatibility mode for privilege checks on large objects."),

src/include/commands/tablespace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "lib/stringinfo.h"
2020
#include "nodes/parsenodes.h"
2121

22+
extern bool allow_in_place_tablespaces;
23+
2224
/* XLOG stuff */
2325
#define XLOG_TBLSPC_CREATE 0x00
2426
#define XLOG_TBLSPC_DROP 0x10

0 commit comments

Comments
 (0)