aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_rewind/pg_rewind.c43
-rw-r--r--src/common/controldata_utils.c94
-rw-r--r--src/include/common/controldata_utils.h6
3 files changed, 101 insertions, 42 deletions
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index aa753bb315f..7f1d6bf48af 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -24,6 +24,7 @@
#include "access/xlog_internal.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
+#include "common/controldata_utils.h"
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/restricted_token.h"
@@ -37,7 +38,6 @@ static void createBackupLabel(XLogRecPtr startpoint, TimeLineID starttli,
static void digestControlFile(ControlFileData *ControlFile, char *source,
size_t size);
-static void updateControlFile(ControlFileData *ControlFile);
static void syncTargetDirectory(void);
static void sanityChecks(void);
static void findCommonAncestorTimeline(XLogRecPtr *recptr, int *tliIndex);
@@ -377,7 +377,7 @@ main(int argc, char **argv)
ControlFile_new.minRecoveryPoint = endrec;
ControlFile_new.minRecoveryPointTLI = endtli;
ControlFile_new.state = DB_IN_ARCHIVE_RECOVERY;
- updateControlFile(&ControlFile_new);
+ update_controlfile(datadir_target, progname, &ControlFile_new);
pg_log(PG_PROGRESS, "syncing target data directory\n");
syncTargetDirectory();
@@ -667,45 +667,6 @@ digestControlFile(ControlFileData *ControlFile, char *src, size_t size)
}
/*
- * Update the target's control file.
- */
-static void
-updateControlFile(ControlFileData *ControlFile)
-{
- char buffer[PG_CONTROL_FILE_SIZE];
-
- /*
- * For good luck, apply the same static assertions as in backend's
- * WriteControlFile().
- */
- StaticAssertStmt(sizeof(ControlFileData) <= PG_CONTROL_MAX_SAFE_SIZE,
- "pg_control is too large for atomic disk writes");
- StaticAssertStmt(sizeof(ControlFileData) <= PG_CONTROL_FILE_SIZE,
- "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
-
- /* Recalculate CRC of control file */
- INIT_CRC32C(ControlFile->crc);
- COMP_CRC32C(ControlFile->crc,
- (char *) ControlFile,
- offsetof(ControlFileData, crc));
- FIN_CRC32C(ControlFile->crc);
-
- /*
- * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
- * the excess over sizeof(ControlFileData), to avoid premature EOF related
- * errors when reading it.
- */
- memset(buffer, 0, PG_CONTROL_FILE_SIZE);
- memcpy(buffer, ControlFile, sizeof(ControlFileData));
-
- open_target_file("global/pg_control", false);
-
- write_target_range(buffer, 0, PG_CONTROL_FILE_SIZE);
-
- close_target_file();
-}
-
-/*
* Sync target data directory to ensure that modifications are safely on disk.
*
* We do this once, for the whole data directory, for performance reasons. At
diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c
index 6289a4343ad..71e67a2edaa 100644
--- a/src/common/controldata_utils.c
+++ b/src/common/controldata_utils.c
@@ -24,8 +24,10 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include "access/xlog_internal.h"
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
+#include "common/file_perm.h"
#include "port/pg_crc32c.h"
#ifndef FRONTEND
#include "storage/fd.h"
@@ -137,3 +139,95 @@ get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p)
return ControlFile;
}
+
+/*
+ * update_controlfile()
+ *
+ * Update controlfile values with the contents given by caller. The
+ * contents to write are included in "ControlFile". Note that it is up
+ * to the caller to fsync the updated file, and to properly lock
+ * ControlFileLock when calling this routine in the backend.
+ */
+void
+update_controlfile(const char *DataDir, const char *progname,
+ ControlFileData *ControlFile)
+{
+ int fd;
+ char buffer[PG_CONTROL_FILE_SIZE];
+ char ControlFilePath[MAXPGPATH];
+
+ /*
+ * Apply the same static assertions as in backend's WriteControlFile().
+ */
+ StaticAssertStmt(sizeof(ControlFileData) <= PG_CONTROL_MAX_SAFE_SIZE,
+ "pg_control is too large for atomic disk writes");
+ StaticAssertStmt(sizeof(ControlFileData) <= PG_CONTROL_FILE_SIZE,
+ "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
+
+ /* Recalculate CRC of control file */
+ INIT_CRC32C(ControlFile->crc);
+ COMP_CRC32C(ControlFile->crc,
+ (char *) ControlFile,
+ offsetof(ControlFileData, crc));
+ FIN_CRC32C(ControlFile->crc);
+
+ /*
+ * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
+ * the excess over sizeof(ControlFileData), to avoid premature EOF related
+ * errors when reading it.
+ */
+ memset(buffer, 0, PG_CONTROL_FILE_SIZE);
+ memcpy(buffer, ControlFile, sizeof(ControlFileData));
+
+ snprintf(ControlFilePath, sizeof(ControlFilePath), "%s/%s", DataDir, XLOG_CONTROL_FILE);
+
+#ifndef FRONTEND
+ if ((fd = OpenTransientFile(ControlFilePath, O_WRONLY | PG_BINARY)) == -1)
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\": %m",
+ ControlFilePath)));
+#else
+ if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
+ pg_file_create_mode)) == -1)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
+ progname, ControlFilePath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ errno = 0;
+ if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
+ {
+ /* if write didn't set errno, assume problem is no disk space */
+ if (errno == 0)
+ errno = ENOSPC;
+
+#ifndef FRONTEND
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not write file \"%s\": %m",
+ ControlFilePath)));
+#else
+ fprintf(stderr, _("%s: could not write \"%s\": %s\n"),
+ progname, ControlFilePath, strerror(errno));
+ exit(EXIT_FAILURE);
+#endif
+ }
+
+#ifndef FRONTEND
+ if (CloseTransientFile(fd))
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not close file \"%s\": %m",
+ ControlFilePath)));
+#else
+ if (close(fd) < 0)
+ {
+ fprintf(stderr, _("%s: could not close file \"%s\": %s\n"),
+ progname, ControlFilePath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+#endif
+}
diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h
index 0ffa2000fc2..95317ebacf2 100644
--- a/src/include/common/controldata_utils.h
+++ b/src/include/common/controldata_utils.h
@@ -12,6 +12,10 @@
#include "catalog/pg_control.h"
-extern ControlFileData *get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p);
+extern ControlFileData *get_controlfile(const char *DataDir,
+ const char *progname,
+ bool *crc_ok_p);
+extern void update_controlfile(const char *DataDir, const char *progname,
+ ControlFileData *ControlFile);
#endif /* COMMON_CONTROLDATA_UTILS_H */