|
7 | 7 | * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
8 | 8 | * Portions Copyright (c) 1994, Regents of the University of California
|
9 | 9 | *
|
10 |
| - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.321 2008/10/31 15:04:59 heikki Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.322 2008/11/09 17:51:15 tgl Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -416,6 +416,7 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname,
|
416 | 416 | const char *recovername, off_t expectedSize);
|
417 | 417 | static void PreallocXlogFiles(XLogRecPtr endptr);
|
418 | 418 | static void RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr);
|
| 419 | +static void ValidateXLOGDirectoryStructure(void); |
419 | 420 | static void CleanupBackupHistory(void);
|
420 | 421 | static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode);
|
421 | 422 | static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);
|
@@ -2824,6 +2825,53 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
|
2824 | 2825 | FreeDir(xldir);
|
2825 | 2826 | }
|
2826 | 2827 |
|
| 2828 | +/* |
| 2829 | + * Verify whether pg_xlog and pg_xlog/archive_status exist. |
| 2830 | + * If the latter does not exist, recreate it. |
| 2831 | + * |
| 2832 | + * It is not the goal of this function to verify the contents of these |
| 2833 | + * directories, but to help in cases where someone has performed a cluster |
| 2834 | + * copy for PITR purposes but omitted pg_xlog from the copy. |
| 2835 | + * |
| 2836 | + * We could also recreate pg_xlog if it doesn't exist, but a deliberate |
| 2837 | + * policy decision was made not to. It is fairly common for pg_xlog to be |
| 2838 | + * a symlink, and if that was the DBA's intent then automatically making a |
| 2839 | + * plain directory would result in degraded performance with no notice. |
| 2840 | + */ |
| 2841 | +static void |
| 2842 | +ValidateXLOGDirectoryStructure(void) |
| 2843 | +{ |
| 2844 | + char path[MAXPGPATH]; |
| 2845 | + struct stat stat_buf; |
| 2846 | + |
| 2847 | + /* Check for pg_xlog; if it doesn't exist, error out */ |
| 2848 | + if (stat(XLOGDIR, &stat_buf) != 0 || |
| 2849 | + !S_ISDIR(stat_buf.st_mode)) |
| 2850 | + ereport(FATAL, |
| 2851 | + (errmsg("required WAL directory \"%s\" does not exist", |
| 2852 | + XLOGDIR))); |
| 2853 | + |
| 2854 | + /* Check for archive_status */ |
| 2855 | + snprintf(path, MAXPGPATH, XLOGDIR "/archive_status"); |
| 2856 | + if (stat(path, &stat_buf) == 0) |
| 2857 | + { |
| 2858 | + /* Check for weird cases where it exists but isn't a directory */ |
| 2859 | + if (!S_ISDIR(stat_buf.st_mode)) |
| 2860 | + ereport(FATAL, |
| 2861 | + (errmsg("required WAL directory \"%s\" does not exist", |
| 2862 | + path))); |
| 2863 | + } |
| 2864 | + else |
| 2865 | + { |
| 2866 | + ereport(LOG, |
| 2867 | + (errmsg("creating missing WAL directory \"%s\"", path))); |
| 2868 | + if (mkdir(path, 0700) < 0) |
| 2869 | + ereport(FATAL, |
| 2870 | + (errmsg("could not create missing directory \"%s\": %m", |
| 2871 | + path))); |
| 2872 | + } |
| 2873 | +} |
| 2874 | + |
2827 | 2875 | /*
|
2828 | 2876 | * Remove previous backup history files. This also retries creation of
|
2829 | 2877 | * .ready files for any backup history files for which XLogArchiveNotify
|
@@ -4878,6 +4926,13 @@ StartupXLOG(void)
|
4878 | 4926 | pg_usleep(60000000L);
|
4879 | 4927 | #endif
|
4880 | 4928 |
|
| 4929 | + /* |
| 4930 | + * Verify that pg_xlog and pg_xlog/archive_status exist. In cases where |
| 4931 | + * someone has performed a copy for PITR, these directories may have |
| 4932 | + * been excluded and need to be re-created. |
| 4933 | + */ |
| 4934 | + ValidateXLOGDirectoryStructure(); |
| 4935 | + |
4881 | 4936 | /*
|
4882 | 4937 | * Initialize on the assumption we want to recover to the same timeline
|
4883 | 4938 | * that's active according to pg_control.
|
|
0 commit comments