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)
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