1 /*-------------------------------------------------------------------------
4 * Common code for control data file output.
7 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/common/controldata_utils.c
14 *-------------------------------------------------------------------------
20 #include "postgres_fe.h"
27 #include "access/xlog_internal.h"
28 #include "catalog/pg_control.h"
29 #include "common/controldata_utils.h"
30 #include "common/file_perm.h"
32 #include "common/logging.h"
34 #include "port/pg_crc32c.h"
38 #include "storage/fd.h"
44 * Get controlfile values. The result is returned as a palloc'd copy of the
47 * crc_ok_p can be used by the caller to see whether the CRC of the control
48 * file data is correct.
51 get_controlfile(const char *DataDir
, bool *crc_ok_p
)
53 ControlFileData
*ControlFile
;
55 char ControlFilePath
[MAXPGPATH
];
61 ControlFile
= palloc(sizeof(ControlFileData
));
62 snprintf(ControlFilePath
, MAXPGPATH
, "%s/global/pg_control", DataDir
);
65 if ((fd
= OpenTransientFile(ControlFilePath
, O_RDONLY
| PG_BINARY
)) == -1)
67 (errcode_for_file_access(),
68 errmsg("could not open file \"%s\" for reading: %m",
71 if ((fd
= open(ControlFilePath
, O_RDONLY
| PG_BINARY
, 0)) == -1)
73 pg_log_fatal("could not open file \"%s\" for reading: %m",
79 r
= read(fd
, ControlFile
, sizeof(ControlFileData
));
80 if (r
!= sizeof(ControlFileData
))
85 (errcode_for_file_access(),
86 errmsg("could not read file \"%s\": %m", ControlFilePath
)));
89 pg_log_fatal("could not read file \"%s\": %m", ControlFilePath
);
96 (errcode(ERRCODE_DATA_CORRUPTED
),
97 errmsg("could not read file \"%s\": read %d of %zu",
98 ControlFilePath
, r
, sizeof(ControlFileData
))));
101 pg_log_fatal("could not read file \"%s\": read %d of %zu",
102 ControlFilePath
, r
, sizeof(ControlFileData
));
109 if (CloseTransientFile(fd
) != 0)
111 (errcode_for_file_access(),
112 errmsg("could not close file \"%s\": %m",
117 pg_log_fatal("could not close file \"%s\": %m", ControlFilePath
);
125 (char *) ControlFile
,
126 offsetof(ControlFileData
, crc
));
129 *crc_ok_p
= EQ_CRC32C(crc
, ControlFile
->crc
);
131 /* Make sure the control file is valid byte order. */
132 if (ControlFile
->pg_control_version
% 65536 == 0 &&
133 ControlFile
->pg_control_version
/ 65536 != 0)
135 elog(ERROR
, _("byte ordering mismatch"));
137 pg_log_warning("possible byte ordering mismatch\n"
138 "The byte ordering used to store the pg_control file might not match the one\n"
139 "used by this program. In that case the results below would be incorrect, and\n"
140 "the PostgreSQL installation would be incompatible with this data directory.");
147 * update_controlfile()
149 * Update controlfile values with the contents given by caller. The
150 * contents to write are included in "ControlFile". "do_sync" can be
151 * optionally used to flush the updated control file. Note that it is up
152 * to the caller to properly lock ControlFileLock when calling this
153 * routine in the backend.
156 update_controlfile(const char *DataDir
,
157 ControlFileData
*ControlFile
, bool do_sync
)
160 char buffer
[PG_CONTROL_FILE_SIZE
];
161 char ControlFilePath
[MAXPGPATH
];
164 * Apply the same static assertions as in backend's WriteControlFile().
166 StaticAssertStmt(sizeof(ControlFileData
) <= PG_CONTROL_MAX_SAFE_SIZE
,
167 "pg_control is too large for atomic disk writes");
168 StaticAssertStmt(sizeof(ControlFileData
) <= PG_CONTROL_FILE_SIZE
,
169 "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
171 /* Recalculate CRC of control file */
172 INIT_CRC32C(ControlFile
->crc
);
173 COMP_CRC32C(ControlFile
->crc
,
174 (char *) ControlFile
,
175 offsetof(ControlFileData
, crc
));
176 FIN_CRC32C(ControlFile
->crc
);
179 * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
180 * the excess over sizeof(ControlFileData), to avoid premature EOF related
181 * errors when reading it.
183 memset(buffer
, 0, PG_CONTROL_FILE_SIZE
);
184 memcpy(buffer
, ControlFile
, sizeof(ControlFileData
));
186 snprintf(ControlFilePath
, sizeof(ControlFilePath
), "%s/%s", DataDir
, XLOG_CONTROL_FILE
);
191 * All errors issue a PANIC, so no need to use OpenTransientFile() and to
192 * worry about file descriptor leaks.
194 if ((fd
= BasicOpenFile(ControlFilePath
, O_RDWR
| PG_BINARY
)) < 0)
196 (errcode_for_file_access(),
197 errmsg("could not open file \"%s\": %m",
200 if ((fd
= open(ControlFilePath
, O_WRONLY
| PG_BINARY
,
201 pg_file_create_mode
)) == -1)
203 pg_log_fatal("could not open file \"%s\": %m", ControlFilePath
);
210 pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE
);
212 if (write(fd
, buffer
, PG_CONTROL_FILE_SIZE
) != PG_CONTROL_FILE_SIZE
)
214 /* if write didn't set errno, assume problem is no disk space */
220 (errcode_for_file_access(),
221 errmsg("could not write file \"%s\": %m",
224 pg_log_fatal("could not write file \"%s\": %m", ControlFilePath
);
229 pgstat_report_wait_end();
235 pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE
);
236 if (pg_fsync(fd
) != 0)
238 (errcode_for_file_access(),
239 errmsg("could not fsync file \"%s\": %m",
241 pgstat_report_wait_end();
245 pg_log_fatal("could not fsync file \"%s\": %m", ControlFilePath
);
255 (errcode_for_file_access(),
256 errmsg("could not close file \"%s\": %m",
259 pg_log_fatal("could not close file \"%s\": %m", ControlFilePath
);