0003-Apply-wal_sync_method-to-pg_control-file.patch
text/x-patch
Filename: 0003-Apply-wal_sync_method-to-pg_control-file.patch
Type: text/x-patch
Part: 2
Patch
Format: format-patch
Series: patch 0003
Subject: Apply wal_sync_method to pg_control file.
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 18 | 1 |
| src/common/controldata_utils.c | 46 | 13 |
| src/include/common/controldata_utils.h | 6 | 1 |
From c9dcb77263a7f86b187231a83083bfbe3a0f30b4 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 31 Jan 2023 21:08:12 +1300
Subject: [PATCH 3/3] Apply wal_sync_method to pg_control file.
When writing out the control file frequently on a standby, we can go a
little faster on some systems by using fdatasync() instead of fsync(),
with no loss of safety. We already respected the special
"wal_sync_method=fsync_writethrough" via a circuitous route, but we
might as well support the full range of methods.
---
src/backend/access/transam/xlog.c | 19 ++++++++-
src/common/controldata_utils.c | 59 ++++++++++++++++++++------
src/include/common/controldata_utils.h | 7 ++-
3 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 9b9c3294e8..27c1cb8273 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4185,7 +4185,24 @@ ReadControlFile(void)
static void
UpdateControlFile(void)
{
- update_controlfile(DataDir, ControlFile, true);
+ int sync_op;
+
+ switch (sync_method)
+ {
+ case SYNC_METHOD_FDATASYNC:
+ sync_op = UPDATE_CONTROLFILE_FDATASYNC;
+ break;
+ case SYNC_METHOD_OPEN:
+ sync_op = UPDATE_CONTROLFILE_O_SYNC;
+ break;
+ case SYNC_METHOD_OPEN_DSYNC:
+ sync_op = UPDATE_CONTROLFILE_O_DSYNC;
+ break;
+ default:
+ sync_op = UPDATE_CONTROLFILE_FSYNC;
+ }
+
+ update_controlfile(DataDir, ControlFile, sync_op);
}
/*
diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c
index 45b43ae546..3fc2a00d44 100644
--- a/src/common/controldata_utils.c
+++ b/src/common/controldata_utils.c
@@ -239,18 +239,39 @@ get_controlfile(const char *DataDir, bool *crc_ok_p)
* update_controlfile()
*
* Update controlfile values with the contents given by caller. The
- * contents to write are included in "ControlFile". "do_sync" can be
- * optionally used to flush the updated control file. Note that it is up
- * to the caller to properly lock ControlFileLock when calling this
- * routine in the backend.
+ * contents to write are included in "ControlFile". "sync_op" can be set
+ * to 0 or a synchronization method UPDATE_CONTROLFILE_XXX. In frontend code,
+ * only 0 and non-zero (fsync) are meaningful.
+ * Note that it is up to the caller to properly lock ControlFileLock when
+ * calling this routine in the backend.
*/
void
update_controlfile(const char *DataDir,
- ControlFileData *ControlFile, bool do_sync)
+ ControlFileData *ControlFile,
+ int sync_op)
{
int fd;
char buffer[PG_CONTROL_FILE_SIZE];
char ControlFilePath[MAXPGPATH];
+ int open_flag;
+
+ switch (sync_op)
+ {
+#ifndef FRONTEND
+#ifdef O_SYNC
+ case UPDATE_CONTROLFILE_O_SYNC:
+ open_flag = O_SYNC;
+ break;
+#endif
+#ifdef O_DSYNC
+ case UPDATE_CONTROLFILE_O_DSYNC:
+ open_flag = O_DSYNC;
+ break;
+#endif
+#endif
+ default:
+ open_flag = 0;
+ }
/* Update timestamp */
ControlFile->time = (pg_time_t) time(NULL);
@@ -278,13 +299,13 @@ update_controlfile(const char *DataDir,
* All errors issue a PANIC, so no need to use OpenTransientFile() and to
* worry about file descriptor leaks.
*/
- if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY)) < 0)
+ if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY | open_flag)) < 0)
ereport(PANIC,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m",
ControlFilePath)));
#else
- if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
+ if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY | open_flag,
pg_file_create_mode)) == -1)
pg_fatal("could not open file \"%s\": %m", ControlFilePath);
#endif
@@ -331,17 +352,29 @@ update_controlfile(const char *DataDir,
pgstat_report_wait_end();
#endif
- if (do_sync)
+ if (sync_op != 0)
{
#ifndef FRONTEND
pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE);
- if (pg_fsync(fd) != 0)
- ereport(PANIC,
- (errcode_for_file_access(),
- errmsg("could not fsync file \"%s\": %m",
- ControlFilePath)));
+ if (sync_op == UPDATE_CONTROLFILE_FDATASYNC)
+ {
+ if (fdatasync(fd) != 0)
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not fdatasync file \"%s\": %m",
+ ControlFilePath)));
+ }
+ else if (sync_op == UPDATE_CONTROLFILE_FSYNC)
+ {
+ if (pg_fsync(fd) != 0)
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not fdatasync file \"%s\": %m",
+ ControlFilePath)));
+ }
pgstat_report_wait_end();
#else
+ /* In frontend code, non-zero sync_op gets you plain fsync(). */
if (fsync(fd) != 0)
pg_fatal("could not fsync file \"%s\": %m", ControlFilePath);
#endif
diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h
index 06825cad85..de6de5571e 100644
--- a/src/include/common/controldata_utils.h
+++ b/src/include/common/controldata_utils.h
@@ -12,9 +12,14 @@
#include "catalog/pg_control.h"
+#define UPDATE_CONTROLFILE_FSYNC 1
+#define UPDATE_CONTROLFILE_FDATASYNC 2
+#define UPDATE_CONTROLFILE_O_SYNC 3
+#define UPDATE_CONTROLFILE_O_DSYNC 4
+
extern ControlFileData *get_controlfile(const char *DataDir, bool *crc_ok_p);
extern void update_controlfile(const char *DataDir,
- ControlFileData *ControlFile, bool do_sync);
+ ControlFileData *ControlFile, int sync_op);
extern int lock_controlfile(int fd, bool exclusive);
#ifdef WIN32
extern int unlock_controlfile(int fd);
--
2.35.1