]> granicus.if.org Git - postgresql/commitdiff
Add a startup check that pg_xlog and pg_xlog/archive_status exist.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 9 Nov 2008 17:51:15 +0000 (17:51 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 9 Nov 2008 17:51:15 +0000 (17:51 +0000)
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
src/backend/access/transam/xlog.c

index 3f62e8fa5a00479fb3a054f47cd2674a65a7e099..1c9b5cfb4bd4547c10b581c123912d8faa7cebfd 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.120 2008/07/18 17:33:17 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.121 2008/11/09 17:51:15 tgl Exp $ -->
 
 <chapter id="backup">
  <title>Backup and Restore</title>
@@ -945,8 +945,6 @@ SELECT pg_stop_backup();
      If you didn't archive <filename>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
-     <filename>pg_xlog/archive_status/</> as well.
     </para>
    </listitem>
    <listitem>
index 77ab05b53d62e46636721e7ecaa87c4fba5cf1d7..f48dd5f7812f508e8f3e011b164fd8a4ec373799 100644 (file)
@@ -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.