diff options
author | Magnus Hagander <magnus@hagander.net> | 2011-01-15 19:18:14 +0100 |
---|---|---|
committer | Magnus Hagander <magnus@hagander.net> | 2011-01-15 19:31:16 +0100 |
commit | 3866ff6149a3b072561e65b3f71f63498e77b6b2 (patch) | |
tree | d08a28dbfe57af234e5d5b67c65c544de03a92da /src/backend | |
parent | 3ab80cfe031b616638eb6956010dcc9cb6426631 (diff) | |
download | postgresql-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.c | 77 |
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); } |