8000 In base backup, only include our own tablespace version directory. · danielcode/postgres@13f9634 · GitHub
[go: up one dir, main page]

Skip to content

Commit 13f9634

Browse files
committed
In base backup, only include our own tablespace version directory.
If you have clusters of different versions pointing to the same tablespace location, we would incorrectly include all the data belonging to the other versions, too. Fixes bug #7986, reported by Sergey Burladyan.
1 parent 6980497 commit 13f9634

File tree

1 file changed

+55
-13
lines changed

1 file changed

+55
-13
lines changed

src/backend/replication/basebackup.c

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <time.h>
1919

2020
#include "access/xlog_internal.h" /* for pg_start/stop_backup */
21+
#include "catalog/catalog.h"
2122
#include "catalog/pg_type.h"
2223
#include "lib/stringinfo.h"
2324
#include "libpq/libpq.h"
@@ -44,6 +45,7 @@ typedef struct
4445

4546

4647
static int64 sendDir(char *path, int basepathlen, bool sizeonly);
48+
static int64 sendTablespace(char *path, bool sizeonly);
4749
static bool sendFile(char *readfilename, char *tarfilename,
4850
struct stat * statbuf, bool missing_ok);
4951
static void sendFileWithContent(const char *filename, const char *content);
@@ -137,7 +139,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
137139
ti = palloc(sizeof(tablespaceinfo));
138140
ti->oid = pstrdup(de->d_name);
139141
ti->path = pstrdup(linkpath);
140-
ti->size = opt->progress ? sendDir(linkpath, strlen(linkpath), true) : -1;
142+
ti->size = opt->progress ? sendTablespace(fullpath, true) : -1;
141143
tablespaces = lappend(tablespaces, ti);
142144
#else
143145

@@ -172,29 +174,26 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
172174
pq_sendint(&buf, 0, 2); /* natts */
173175
pq_endmessage(&buf);
174176

175-
/* In the main tar, include the backup_label first. */
176-
if (ti->path == NULL)
177-
sendFileWithContent(BACKUP_LABEL_FILE, labelfile);
178-
179-
sendDir(ti->path == NULL ? "." : ti->path,
180-
ti->path == NULL ? 1 : strlen(ti->path),
181-
false);
182-
183-
/* In the main tar, include pg_control last. */
184177
if (ti->path == NULL)
185178
{
186179
struct stat statbuf;
187180

181+
/* In the main tar, include the backup_label first... */
182+
sendFileWithContent(BACKUP_LABEL_FILE, labelfile);
183+
184+
/* ... then the bulk of the files ... */
185+
sendDir(".", 1, false);
186+
187+
/* ... and pg_control after everything else. */
188188
if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
189-
{
190189
ereport(ERROR,
191190
(errcode_for_file_access(),
192191
errmsg("could not stat control file \"%s\": %m",
193192
XLOG_CONTROL_FILE)));
194-
}
195-
196193
sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false);
197194
}
195+
else
196+
sendTablespace(ti->path, false);
198197

199198
/*
200199
* If we're including WAL, and this is the main data directory we
@@ -722,6 +721,49 @@ sendFileWithContent(const char *filename, const char *content)
722721
}
723722
}
724723

724+
/*
725+
* Include the tablespace directory pointed to by 'path' in the output tar
726+
* stream. If 'sizeonly' is true, we just calculate a total length and return
727+
* it, without actually sending anything.
728+
*/
729+
static int64
730+
sendTablespace(char *path, bool sizeonly)
731+
{
732+
int64 size;
733+
char pathbuf[MAXPGPATH];
734+
struct stat statbuf;
735+
736+
/*
737+
* 'path' points to the tablespace location, but we only want to include
738+
* the version directory in it that belongs to us.
739+
*/
740+
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path,
741+
TABLESPACE_VERSION_DIRECTORY);
742+
743+
/*
744+
* Store a directory entry in the tar file so we get the permissions right.
745+
*/
746+
if (lstat(pathbuf, &statbuf) != 0)
747+
{
748+
if (errno != ENOENT)
749+
ereport(ERROR,
750+
(errcode_for_file_access(),
751+
errmsg("could not stat file or directory \"%s\": %m",
752+
pathbuf)));
753+
754+
/* If the tablespace went away while scanning, it's no error. */
755+
return 0;
756+
}
757+
if (!sizeonly)
758+
_tarWriteHeader(TABLESPACE_VERSION_DIRECTORY, NULL, &statbuf);
759+
size = 512; /* Size of the header just added */
760+
761+
/* Send all the files in the tablespace version directory */
762+
size += sendDir(pathbuf, strlen(path), sizeonly);
763+
764+
return size;
765+
}
766+
725767
/*
726768
* Include all files from the given directory in the output tar stream. If
727769
* 'sizeonly' is true, we just calculate a total length and return it, without

0 commit comments

Comments
 (0)
0