8000 Allow "in place" tablespaces. · postgres/postgres@258c896 · GitHub
[go: up one dir, main page]

Skip to content

Commit 258c896

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 9e3e1ac commit 258c896

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
@@ -8700,6 +8700,25 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
87008700
</para>
87018701

87028702
<variablelist>
8703+
<varlistentry id="guc-allow-in-place-tablespaces" xreflabel="allow_in_place_tablespaces">
8704+
<term><varname>allow_in_place_tablespaces</varname> (<type>boolean</type>)
8705+
<indexterm>
8706+
<primary><varname>allow_in_place_tablespaces</varname> configuration parameter</primary>
8707+
</indexterm>
8708+
</term>
8709+
<listitem>
8710+
<para>
8711+
Allows tablespaces to be created as directories inside
8712+
<filename>pg_tblspc</filename>, when an empty location string
8713+
is provided to the <command>CREATE TABLESPACE</command> command. This
8714+
is intended to allow testing replication scenarios where primary and
8715+
standby servers are running on the same machine. Such directories
8716+
are likely to confuse backup tools that expect to find only symbolic
8717+
links in that location. Only superusers can change this setting.
8718+
</para>
8719+
</listitem>
8720+
</varlistentry>
8721+
87038722
<varlistentry id="guc-allow-system-table-mods" xreflabel="allow_system_table_mods">
87048723
<term><varname>allow_system_table_mods</varname> (<type>boolean</type>)
87058724
<indexterm>

src/backend/access/transam/xlog.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10819,13 +10819,33 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
1081910819
int rllen;
1082010820
StringInfoData buflinkpath;
1082110821
char *s = linkpath;
10822+
#ifndef WIN32
10823+
struct stat st;
10824+
#endif
1082210825

1082310826
/* Skip special stuff */
1082410827
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
1082510828
continue;
1082610829

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

10832+
/*
10833+
* Skip anything that isn't a symlink/junction. For testing only,
10834+
* we sometimes use allow_in_place_tablespaces to create
10835+
* directories directly under pg_tblspc, which would fail below.
10836+
*/
10837+
#ifndef WIN32
10838+
if (lstat(fullpath, &st) < 0)
10839+
ereport(LOG,
10840+
(errcode_for_file_access(),
10841+
errmsg("could not stat file \"%s\": %m",
10842+
fullpath)));
10843+
else if (!S_ISLNK(st.st_mode))
10844+
#else /* WIN32 */
10845+
if (!pgwin32_is_junction(fullpath))
10846+
#endif
10847+
continue;
10848+
1082910849
#if defined(HAVE_READLINK) || defined(WIN32)
1083010850
rllen = readlink(fullpath, linkpath, sizeof(linkpath));
1083110851
if (rllen < 0)

src/backend/commands/tablespace.c

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

9293

9394
static void create_tablespace_directories(const char *location,
@@ -242,6 +243,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
242243
char *location;
243244
Oid ownerId;
244245
Datum newOptions;
246+
bool in_place;
245247

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

272+
in_place = allow_in_place_tablespaces && strlen(location) == 0;
273+
270274
/*
271275
* Allowing relative paths seems risky
272276
*
273-
* this also helps us ensure that location is not empty or whitespace
277+
* This also helps us ensure that location is not empty or whitespace,
278+
* unless specifying a developer-only in-place tablespace.
274279
*/
275-
if (!is_absolute_path(location))
280+
if (!in_place && !is_absolute_path(location))
276281
ereport(ERROR,
277282
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
278283
errmsg("tablespace location must be an absolute path")));
@@ -579,16 +584,36 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
579584
char *linkloc;
580585
char *location_with_version_dir;
581586
struct stat st;
587+
bool in_place;
582588

583589
linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
584-
location_with_version_dir = psprintf("%s/%s", location,
590+
591+
/*
592+
* If we're asked to make an 'in place' tablespace, create the directory
593+
* directly where the symlink would normally go. This is a developer-only
594+
* option for now, to facilitate regression testing.
595+
*/
596+
in_place = strlen(location) == 0;
597+
598+
if (in_place)
599+
{
600+
if (MakePGDirectory(linkloc) < 0 && errno != EEXIST)
601+
ereport(ERROR,
602+
(errcode_for_file_access(),
603+
errmsg("could not create directory \"%s\": %m",
604+
linkloc)));
605+
}
606+
607+
location_with_version_dir = psprintf("%s/%s", in_place ? linkloc : location,
585608
TABLESPACE_VERSION_DIRECTORY);
586609

587610
/*
588611
* Attempt to coerce target directory to safe permissions. If this fails,
589-
* it doesn't exist or has the wrong owner.
612+
* it doesn't exist or has the wrong owner. Not needed for in-place mode,
613+
* because in that case we created the directory with the desired
614+
* permissions.
590615
*/
591-
if (chmod(location, pg_dir_create_mode) != 0)
616+
if (!in_place && chmod(location, pg_dir_create_mode) != 0)
592617
{
593618
if (errno == ENOENT)
594619
ereport(ERROR,
@@ -637,13 +662,13 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
637662
/*
638663
* In recovery, remove old symlink, in case it points to the wrong place.
639664
*/
640-
if (InRecovery)
665+
if (!in_place && InRecovery)
641666
remove_tablespace_symlink(linkloc);
642667

643668
/*
644669
* Create the symlink under PGDATA
645670
*/
646-
if (symlink(location, linkloc) < 0)
671+
if (!in_place && symlink(location, linkloc) < 0)
647672
ereport(ERROR,
648673
(errcode_for_file_access(),
649674
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
@@ -16,6 +16,7 @@
1616

1717
#include <sys/file.h>
1818
#include <signal.h>
19+
#include <sys/stat.h>
1920
#include <dirent.h>
2021
#include <fcntl.h>
2122
#include <math.h>
@@ -500,6 +501,9 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
500501
char sourcepath[MAXPGPATH];
501502
char targetpath[MAXPGPATH];
502503
int rllen;
504+
#ifndef WIN32
505+
struct stat st;
506+
#endif
503507

504508
/*
505509
* It's useful to apply this function to pg_class.reltablespace, wherein
@@ -524,6 +528,31 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
524528
*/
525529
snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
526530

531+
/*
532+
* Before reading the link, check if the source path is a link or a
533+
* junction point. Note that a directory is possible for a tablespace
534+
* created with allow_in_place_tablespaces enabled. If a directory is
535+
* found, a relative path to the data directory is returned.
536+
*/
537+
#ifdef WIN32
538+
if (!pgwin32_is_junction(sourcepath))
539+
PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
540+
#else
541+
if (lstat(sourcepath, &st) < 0)
542+
{
543+
ereport(ERROR,
544+
(errcode_for_file_access(),
545+
errmsg("could not stat file \"%s\": %m",
546+
sourcepath)));
547+
}
548+
549+
if (!S_ISLNK(st.st_mode))
550+
PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
551+
#endif
552+
553+
/*
554+
* In presence of a link or a junction point, return the path pointing to.
555+
*/
527556
rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
528557
if (rllen < 0)
529558
ereport(ERROR,

src/backend/utils/misc/guc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "catalog/pg_authid.h"
3838
#include "commands/async.h"
3939
#include "commands/prepare.h"
40+
#include "commands/tablespace.h"
4041
#include "commands/user.h"
4142
#include "commands/vacuum.h"
4243
#include "commands/variable.h"
@@ -1675,6 +1676,17 @@ static struct config_bool ConfigureNamesBool[] =
16751676
NULL, NULL, NULL
16761677
},
16771678

1679+
{
1680+
{"allow_in_place_tablespaces", PGC_SUSET, DEVELOPER_OPTIONS,
1681+
gettext_noop("Allows tablespaces directly inside pg_tblspc, for testing."),
1682+
NULL,
1683+
GUC_NOT_IN_SAMPLE
1684+
},
1685+
&allow_in_place_tablespaces,
1686+
false,
1687+
NULL, NULL, NULL
1688+
},
1689+
16781690
{
16791691
{"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
16801692
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)
0