PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
controldata_utils.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * controldata_utils.c
4 * Common code for control data file output.
5 *
6 *
7 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/common/controldata_utils.c
13 *
14 *-------------------------------------------------------------------------
15 */
16
17#ifndef FRONTEND
18#include "postgres.h"
19#else
20#include "postgres_fe.h"
21#endif
22
23#include <unistd.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <time.h>
27
29#include "catalog/pg_control.h"
31#ifdef FRONTEND
32#include "common/file_perm.h"
33#include "common/logging.h"
34#endif
35#include "port/pg_crc32c.h"
36
37#ifndef FRONTEND
38#include "pgstat.h"
39#include "storage/fd.h"
40#endif
41
42/*
43 * get_controlfile()
44 *
45 * Get controlfile values. The result is returned as a palloc'd copy of the
46 * control file data.
47 *
48 * crc_ok_p can be used by the caller to see whether the CRC of the control
49 * file data is correct.
50 */
52get_controlfile(const char *DataDir, bool *crc_ok_p)
53{
54 char ControlFilePath[MAXPGPATH];
55
56 snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
57
58 return get_controlfile_by_exact_path(ControlFilePath, crc_ok_p);
59}
60
61/*
62 * get_controlfile_by_exact_path()
63 *
64 * As above, but the caller specifies the path to the control file itself,
65 * rather than the path to the data directory.
66 */
68get_controlfile_by_exact_path(const char *ControlFilePath, bool *crc_ok_p)
69{
71 int fd;
73 int r;
74#ifdef FRONTEND
75 pg_crc32c last_crc;
76 int retries = 0;
77#endif
78
79 Assert(crc_ok_p);
80
82
83#ifdef FRONTEND
84 INIT_CRC32C(last_crc);
85
86retry:
87#endif
88
89#ifndef FRONTEND
90 if ((fd = OpenTransientFile(ControlFilePath, O_RDONLY | PG_BINARY)) == -1)
93 errmsg("could not open file \"%s\" for reading: %m",
94 ControlFilePath)));
95#else
96 if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
97 pg_fatal("could not open file \"%s\" for reading: %m",
98 ControlFilePath);
99#endif
100
101 r = read(fd, ControlFile, sizeof(ControlFileData));
102 if (r != sizeof(ControlFileData))
103 {
104 if (r < 0)
105#ifndef FRONTEND
108 errmsg("could not read file \"%s\": %m", ControlFilePath)));
109#else
110 pg_fatal("could not read file \"%s\": %m", ControlFilePath);
111#endif
112 else
113#ifndef FRONTEND
116 errmsg("could not read file \"%s\": read %d of %zu",
117 ControlFilePath, r, sizeof(ControlFileData))));
118#else
119 pg_fatal("could not read file \"%s\": read %d of %zu",
120 ControlFilePath, r, sizeof(ControlFileData));
121#endif
122 }
123
124#ifndef FRONTEND
125 if (CloseTransientFile(fd) != 0)
128 errmsg("could not close file \"%s\": %m",
129 ControlFilePath)));
130#else
131 if (close(fd) != 0)
132 pg_fatal("could not close file \"%s\": %m", ControlFilePath);
133#endif
134
135 /* Check the CRC. */
138 (char *) ControlFile,
139 offsetof(ControlFileData, crc));
141
142 *crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
143
144#ifdef FRONTEND
145
146 /*
147 * If the server was writing at the same time, it is possible that we read
148 * partially updated contents on some systems. If the CRC doesn't match,
149 * retry a limited number of times until we compute the same bad CRC twice
150 * in a row with a short sleep in between. Then the failure is unlikely
151 * to be due to a concurrent write.
152 */
153 if (!*crc_ok_p &&
154 (retries == 0 || !EQ_CRC32C(crc, last_crc)) &&
155 retries < 10)
156 {
157 retries++;
158 last_crc = crc;
159 pg_usleep(10000);
160 goto retry;
161 }
162#endif
163
164 /* Make sure the control file is valid byte order. */
165 if (ControlFile->pg_control_version % 65536 == 0 &&
166 ControlFile->pg_control_version / 65536 != 0)
167#ifndef FRONTEND
168 elog(ERROR, _("byte ordering mismatch"));
169#else
170 pg_log_warning("possible byte ordering mismatch\n"
171 "The byte ordering used to store the pg_control file might not match the one\n"
172 "used by this program. In that case the results below would be incorrect, and\n"
173 "the PostgreSQL installation would be incompatible with this data directory.");
174#endif
175
176 return ControlFile;
177}
178
179/*
180 * update_controlfile()
181 *
182 * Update controlfile values with the contents given by caller. The
183 * contents to write are included in "ControlFile". "do_sync" can be
184 * optionally used to flush the updated control file. Note that it is up
185 * to the caller to properly lock ControlFileLock when calling this
186 * routine in the backend.
187 */
188void
191{
192 int fd;
193 char buffer[PG_CONTROL_FILE_SIZE];
194 char ControlFilePath[MAXPGPATH];
195
196 /* Update timestamp */
197 ControlFile->time = (pg_time_t) time(NULL);
198
199 /* Recalculate CRC of control file */
202 (char *) ControlFile,
203 offsetof(ControlFileData, crc));
205
206 /*
207 * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
208 * the excess over sizeof(ControlFileData), to avoid premature EOF related
209 * errors when reading it.
210 */
211 memset(buffer, 0, PG_CONTROL_FILE_SIZE);
212 memcpy(buffer, ControlFile, sizeof(ControlFileData));
213
214 snprintf(ControlFilePath, sizeof(ControlFilePath), "%s/%s", DataDir, XLOG_CONTROL_FILE);
215
216#ifndef FRONTEND
217
218 /*
219 * All errors issue a PANIC, so no need to use OpenTransientFile() and to
220 * worry about file descriptor leaks.
221 */
222 if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY)) < 0)
225 errmsg("could not open file \"%s\": %m",
226 ControlFilePath)));
227#else
228 if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
229 pg_file_create_mode)) == -1)
230 pg_fatal("could not open file \"%s\": %m", ControlFilePath);
231#endif
232
233 errno = 0;
234#ifndef FRONTEND
235 pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE);
236#endif
238 {
239 /* if write didn't set errno, assume problem is no disk space */
240 if (errno == 0)
241 errno = ENOSPC;
242
243#ifndef FRONTEND
246 errmsg("could not write file \"%s\": %m",
247 ControlFilePath)));
248#else
249 pg_fatal("could not write file \"%s\": %m", ControlFilePath);
250#endif
251 }
252#ifndef FRONTEND
254#endif
255
256 if (do_sync)
257 {
258#ifndef FRONTEND
259 pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE);
260 if (pg_fsync(fd) != 0)
263 errmsg("could not fsync file \"%s\": %m",
264 ControlFilePath)));
266#else
267 if (fsync(fd) != 0)
268 pg_fatal("could not fsync file \"%s\": %m", ControlFilePath);
269#endif
270 }
271
272 if (close(fd) != 0)
273 {
274#ifndef FRONTEND
277 errmsg("could not close file \"%s\": %m",
278 ControlFilePath)));
279#else
280 pg_fatal("could not close file \"%s\": %m", ControlFilePath);
281#endif
282 }
283}
#define Assert(condition)
Definition: c.h:812
#define PG_BINARY
Definition: c.h:1227
void update_controlfile(const char *DataDir, ControlFileData *ControlFile, bool do_sync)
ControlFileData * get_controlfile(const char *DataDir, bool *crc_ok_p)
ControlFileData * get_controlfile_by_exact_path(const char *ControlFilePath, bool *crc_ok_p)
int errcode_for_file_access(void)
Definition: elog.c:876
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define _(x)
Definition: elog.c:90
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
int CloseTransientFile(int fd)
Definition: fd.c:2831
int BasicOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1086
int pg_fsync(int fd)
Definition: fd.c:385
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2655
#define palloc_object(type)
Definition: fe_memutils.h:74
int pg_file_create_mode
Definition: file_perm.c:19
char * DataDir
Definition: globals.c:70
static bool do_sync
Definition: initdb.c:164
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
#define read(a, b, c)
Definition: win32.h:13
#define pg_fatal(...)
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
#define MAXPGPATH
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:250
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:98
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:103
return crc
#define pg_log_warning(...)
Definition: pgfnames.c:24
int64 pg_time_t
Definition: pgtime.h:23
#define snprintf
Definition: port.h:238
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void pg_usleep(long microsec)
Definition: signal.c:53
uint32 pg_control_version
Definition: pg_control.h:125
pg_time_t time
Definition: pg_control.h:132
pg_crc32c crc
Definition: pg_control.h:232
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101
#define fsync(fd)
Definition: win32_port.h:85
static ControlFileData * ControlFile
Definition: xlog.c:574
#define XLOG_CONTROL_FILE