aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorMagnus Hagander <magnus@hagander.net>2011-01-15 19:18:14 +0100
committerMagnus Hagander <magnus@hagander.net>2011-01-15 19:31:16 +0100
commit3866ff6149a3b072561e65b3f71f63498e77b6b2 (patch)
treed08a28dbfe57af234e5d5b67c65c544de03a92da /src/backend
parent3ab80cfe031b616638eb6956010dcc9cb6426631 (diff)
downloadpostgresql-3866ff6149a3b072561e65b3f71f63498e77b6b2.tar.gz
postgresql-3866ff6149a3b072561e65b3f71f63498e77b6b2.zip
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.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/replication/basebackup.c77
1 files changed, 40 insertions, 37 deletions
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 1ed5e2a6c9e..b4d5bbe412e 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -40,7 +40,7 @@ static void send_int8_string(StringInfoData *buf, int64 intval);
static void SendBackupHeader(List *tablespaces);
static void SendBackupDirectory(char *location, char *spcoid);
static void base_backup_cleanup(int code, Datum arg);
-static void perform_base_backup(const char *backup_label, List *tablespaces);
+static void perform_base_backup(const char *backup_label, bool progress, DIR *tblspcdir);
typedef struct
{
@@ -67,13 +67,50 @@ base_backup_cleanup(int code, Datum arg)
* clobbered by longjmp" from stupider versions of gcc.
*/
static void
-perform_base_backup(const char *backup_label, List *tablespaces)
+perform_base_backup(const char *backup_label, bool progress, DIR *tblspcdir)
{
do_pg_start_backup(backup_label, true);
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
{
+ List *tablespaces = NIL;
ListCell *lc;
+ struct dirent *de;
+ tablespaceinfo *ti;
+
+
+ /* Add a node for the base directory */
+ ti = palloc0(sizeof(tablespaceinfo));
+ ti->size = progress ? sendDir(".", 1, true) : -1;
+ tablespaces = lappend(tablespaces, ti);
+
+ /* Collect information about all tablespaces */
+ while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
+ {
+ char fullpath[MAXPGPATH];
+ char linkpath[MAXPGPATH];
+
+ /* Skip special stuff */
+ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+ continue;
+
+ snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
+
+ MemSet(linkpath, 0, sizeof(linkpath));
+ if (readlink(fullpath, linkpath, sizeof(linkpath) - 1) == -1)
+ {
+ ereport(WARNING,
+ (errmsg("unable to read symbolic link %s: %m", fullpath)));
+ continue;
+ }
+
+ ti = palloc(sizeof(tablespaceinfo));
+ ti->oid = pstrdup(de->d_name);
+ ti->path = pstrdup(linkpath);
+ ti->size = progress ? sendDir(linkpath, strlen(linkpath), true) : -1;
+ tablespaces = lappend(tablespaces, ti);
+ }
+
/* Send tablespace header */
SendBackupHeader(tablespaces);
@@ -101,9 +138,6 @@ void
SendBaseBackup(const char *backup_label, bool progress)
{
DIR *dir;
- struct dirent *de;
- List *tablespaces = NIL;
- tablespaceinfo *ti;
MemoryContext backup_context;
MemoryContext old_context;
@@ -134,41 +168,10 @@ SendBaseBackup(const char *backup_label, bool progress)
ereport(ERROR,
(errmsg("unable to open directory pg_tblspc: %m")));
- /* Add a node for the base directory */
- ti = palloc0(sizeof(tablespaceinfo));
- ti->size = progress ? sendDir(".", 1, true) : -1;
- tablespaces = lappend(tablespaces, ti);
-
- /* Collect information about all tablespaces */
- while ((de = ReadDir(dir, "pg_tblspc")) != NULL)
- {
- char fullpath[MAXPGPATH];
- char linkpath[MAXPGPATH];
-
- /* Skip special stuff */
- if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
- continue;
-
- snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
-
- MemSet(linkpath, 0, sizeof(linkpath));
- if (readlink(fullpath, linkpath, sizeof(linkpath) - 1) == -1)
- {
- ereport(WARNING,
- (errmsg("unable to read symbolic link %s: %m", fullpath)));
- continue;
- }
+ perform_base_backup(backup_label, progress, dir);
- ti = palloc(sizeof(tablespaceinfo));
- ti->oid = pstrdup(de->d_name);
- ti->path = pstrdup(linkpath);
- ti->size = progress ? sendDir(linkpath, strlen(linkpath), true) : -1;
- tablespaces = lappend(tablespaces, ti);
- }
FreeDir(dir);
- perform_base_backup(backup_label, tablespaces);
-
MemoryContextSwitchTo(old_context);
MemoryContextDelete(backup_context);
}