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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy