From 1d577f5e49400465bd8cc3f91b67d03a551528c3 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 9 Nov 2008 17:51:15 +0000 Subject: [PATCH] Add a startup check that pg_xlog and pg_xlog/archive_status exist. If the latter doesn't exist, automatically recreate it. (We don't do this for pg_xlog, though, per discussion.) Jonah Harris --- doc/src/sgml/backup.sgml | 4 +-- src/backend/access/transam/xlog.c | 57 ++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 3f62e8fa5a..1c9b5cfb4b 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -1,4 +1,4 @@ - + Backup and Restore @@ -945,8 +945,6 @@ SELECT pg_stop_backup(); If you didn't archive pg_xlog/ at all, then recreate it, being careful to ensure that you re-establish it as a symbolic link if you had it set up that way before. - Be sure to recreate the subdirectory - pg_xlog/archive_status/ as well. diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 77ab05b53d..f48dd5f781 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.321 2008/10/31 15:04:59 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.322 2008/11/09 17:51:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -416,6 +416,7 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize); static void PreallocXlogFiles(XLogRecPtr endptr); static void RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr); +static void ValidateXLOGDirectoryStructure(void); static void CleanupBackupHistory(void); static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode); static bool ValidXLOGHeader(XLogPageHeader hdr, int emode); @@ -2824,6 +2825,53 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr) FreeDir(xldir); } +/* + * Verify whether pg_xlog and pg_xlog/archive_status exist. + * If the latter does not exist, recreate it. + * + * It is not the goal of this function to verify the contents of these + * directories, but to help in cases where someone has performed a cluster + * copy for PITR purposes but omitted pg_xlog from the copy. + * + * We could also recreate pg_xlog if it doesn't exist, but a deliberate + * policy decision was made not to. It is fairly common for pg_xlog to be + * a symlink, and if that was the DBA's intent then automatically making a + * plain directory would result in degraded performance with no notice. + */ +static void +ValidateXLOGDirectoryStructure(void) +{ + char path[MAXPGPATH]; + struct stat stat_buf; + + /* Check for pg_xlog; if it doesn't exist, error out */ + if (stat(XLOGDIR, &stat_buf) != 0 || + !S_ISDIR(stat_buf.st_mode)) + ereport(FATAL, + (errmsg("required WAL directory \"%s\" does not exist", + XLOGDIR))); + + /* Check for archive_status */ + snprintf(path, MAXPGPATH, XLOGDIR "/archive_status"); + if (stat(path, &stat_buf) == 0) + { + /* Check for weird cases where it exists but isn't a directory */ + if (!S_ISDIR(stat_buf.st_mode)) + ereport(FATAL, + (errmsg("required WAL directory \"%s\" does not exist", + path))); + } + else + { + ereport(LOG, + (errmsg("creating missing WAL directory \"%s\"", path))); + if (mkdir(path, 0700) < 0) + ereport(FATAL, + (errmsg("could not create missing directory \"%s\": %m", + path))); + } +} + /* * Remove previous backup history files. This also retries creation of * .ready files for any backup history files for which XLogArchiveNotify @@ -4878,6 +4926,13 @@ StartupXLOG(void) pg_usleep(60000000L); #endif + /* + * Verify that pg_xlog and pg_xlog/archive_status exist. In cases where + * someone has performed a copy for PITR, these directories may have + * been excluded and need to be re-created. + */ + ValidateXLOGDirectoryStructure(); + /* * Initialize on the assumption we want to recover to the same timeline * that's active according to pg_control. -- 2.40.0