Skip to content

Commit 3866ff6

Browse files
committed
Enumerate available tablespaces after starting the backup
This closes a race condition where if a tablespace was created after the enumeration happened but before the do_pg_start_backup() was called, the backup would be incomplete. Now that it's done while we are in backup mode, WAL replay will recreate it during restore. Noted by Heikki.
1 parent 3ab80cf commit 3866ff6

File tree

1 file changed

+40
-37
lines changed

1 file changed

+40
-37
lines changed

src/backend/replication/basebackup.c

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static void send_int8_string(StringInfoData *buf, int64 intval);
4040
static void SendBackupHeader(List *tablespaces);
4141
static void SendBackupDirectory(char *location, char *spcoid);
4242
static void base_backup_cleanup(int code, Datum arg);
43-
static void perform_base_backup(const char *backup_label, List *tablespaces);
43+
static void perform_base_backup(const char *backup_label, bool progress, DIR *tblspcdir);
4444

4545
typedef struct
4646
{
@@ -67,13 +67,50 @@ base_backup_cleanup(int code, Datum arg)
6767
* clobbered by longjmp" from stupider versions of gcc.
6868
*/
6969
static void
70-
perform_base_backup(const char *backup_label, List *tablespaces)
70+
perform_base_backup(const char *backup_label, bool progress, DIR *tblspcdir)
7171
{
7272
do_pg_start_backup(backup_label, true);
7373

7474
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
7575
{
76+
List *tablespaces = NIL;
7677
ListCell *lc;
78+
struct dirent *de;
79+
tablespaceinfo *ti;
80+
81+
82+
/* Add a node for the base directory */
83+
ti = palloc0(sizeof(tablespaceinfo));
84+
ti->size = progress ? sendDir(".", 1, true) : -1;
85+
tablespaces = lappend(tablespaces, ti);
86+
87+
/* Collect information about all tablespaces */
88+
while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
89+
{
90+
char fullpath[MAXPGPATH];
91+
char linkpath[MAXPGPATH];
92+
93+
/* Skip special stuff */
94+
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
95+
continue;
96+
97+
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
98+
99+
MemSet(linkpath, 0, sizeof(linkpath));
100+
if (readlink(fullpath, linkpath, sizeof(linkpath) - 1) == -1)
101+
{
102+
ereport(WARNING,
103+
(errmsg("unable to read symbolic link %s: %m", fullpath)));
104+
continue;
105+
}
106+
107+
ti = palloc(sizeof(tablespaceinfo));
108+
ti->oid = pstrdup(de->d_name);
109+
ti->path = pstrdup(linkpath);
110+
ti->size = progress ? sendDir(linkpath, strlen(linkpath), true) : -1;
111+
tablespaces = lappend(tablespaces, ti);
112+
}
113+
77114

78115
/* Send tablespace header */
79116
SendBackupHeader(tablespaces);
@@ -101,9 +138,6 @@ void
101138
SendBaseBackup(const char *backup_label, bool progress)
102139
{
103140
DIR *dir;
104-
struct dirent *de;
105-
List *tablespaces = NIL;
106-
tablespaceinfo *ti;
107141
MemoryContext backup_context;
108142
MemoryContext old_context;
109143

@@ -134,41 +168,10 @@ SendBaseBackup(const char *backup_label, bool progress)
134168
ereport(ERROR,
135169
(errmsg("unable to open directory pg_tblspc: %m")));
136170

137-
/* Add a node for the base directory */
138-
ti = palloc0(sizeof(tablespaceinfo));
139-
ti->size = progress ? sendDir(".", 1, true) : -1;
140-
tablespaces = lappend(tablespaces, ti);
141-
142-
/* Collect information about all tablespaces */
143-
while ((de = ReadDir(dir, "pg_tblspc")) != NULL)
144-
{
145-
char fullpath[MAXPGPATH];
146-
char linkpath[MAXPGPATH];
147-
148-
/* Skip special stuff */
149-
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
150-
continue;
151-
152-
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
153-
154-
MemSet(linkpath, 0, sizeof(linkpath));
155-
if (readlink(fullpath, linkpath, sizeof(linkpath) - 1) == -1)
156-
{
157-
ereport(WARNING,
158-
(errmsg("unable to read symbolic link %s: %m", fullpath)));
159-
continue;
160-
}
171+
perform_base_backup(backup_label, progress, dir);
161172

162-
ti = palloc(sizeof(tablespaceinfo));
163-
ti->oid = pstrdup(de->d_name);
164-
ti->path = pstrdup(linkpath);
165-
ti->size = progress ? sendDir(linkpath, strlen(linkpath), true) : -1;
166-
tablespaces = lappend(tablespaces, ti);
167-
}
168173
FreeDir(dir);
169174

170-
perform_base_backup(backup_label, tablespaces);
171-
172175
MemoryContextSwitchTo(old_context);
173176
MemoryContextDelete(backup_context);
174177
}

0 commit comments

Comments
 (0)