PostgreSQL Source Code  git master
controldata_utils.c File Reference
#include "postgres.h"
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.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"
#include "pgstat.h"
#include "storage/fd.h"
Include dependency graph for controldata_utils.c:

Go to the source code of this file.

Functions

ControlFileDataget_controlfile (const char *DataDir, bool *crc_ok_p)
 
ControlFileDataget_controlfile_by_exact_path (const char *ControlFilePath, bool *crc_ok_p)
 
void update_controlfile (const char *DataDir, ControlFileData *ControlFile, bool do_sync)
 

Function Documentation

◆ get_controlfile()

ControlFileData* get_controlfile ( const char *  DataDir,
bool crc_ok_p 
)

Definition at line 52 of file controldata_utils.c.

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 }
ControlFileData * get_controlfile_by_exact_path(const char *ControlFilePath, bool *crc_ok_p)
char * DataDir
Definition: globals.c:70
#define MAXPGPATH
#define snprintf
Definition: port.h:238

References DataDir, get_controlfile_by_exact_path(), MAXPGPATH, and snprintf.

Referenced by get_control_dbstate(), get_standby_sysid(), main(), modify_subscriber_sysid(), pg_control_checkpoint(), pg_control_init(), pg_control_recovery(), and pg_control_system().

◆ get_controlfile_by_exact_path()

ControlFileData* get_controlfile_by_exact_path ( const char *  ControlFilePath,
bool crc_ok_p 
)

Definition at line 68 of file controldata_utils.c.

69 {
71  int fd;
72  pg_crc32c crc;
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 
86 retry:
87 #endif
88 
89 #ifndef FRONTEND
90  if ((fd = OpenTransientFile(ControlFilePath, O_RDONLY | PG_BINARY)) == -1)
91  ereport(ERROR,
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
106  ereport(ERROR,
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
114  ereport(ERROR,
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)
126  ereport(ERROR,
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. */
136  INIT_CRC32C(crc);
138  (char *) ControlFile,
139  offsetof(ControlFileData, crc));
140  FIN_CRC32C(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 }
#define Assert(condition)
Definition: c.h:861
#define PG_BINARY
Definition: c.h:1276
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 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:2832
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2656
#define palloc_object(type)
Definition: fe_memutils.h:62
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13
#define pg_fatal(...)
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
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
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_crc32c crc
Definition: pg_control.h:232
static ControlFileData * ControlFile
Definition: xlog.c:573

References _, Assert, close, CloseTransientFile(), COMP_CRC32C, ControlFile, ControlFileData::crc, crc, elog, EQ_CRC32C, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), ERROR, fd(), FIN_CRC32C, INIT_CRC32C, OpenTransientFile(), palloc_object, PG_BINARY, ControlFileData::pg_control_version, pg_fatal, pg_log_warning, pg_usleep(), and read.

Referenced by check_control_files(), get_controlfile(), and verify_control_file().

◆ update_controlfile()

void update_controlfile ( const char *  DataDir,
ControlFileData ControlFile,
bool  do_sync 
)

Definition at line 189 of file controldata_utils.c.

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)
223  ereport(PANIC,
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
244  ereport(PANIC,
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)
261  ereport(PANIC,
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
275  ereport(PANIC,
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 PANIC
Definition: elog.h:42
int BasicOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1087
int pg_fsync(int fd)
Definition: fd.c:386
int pg_file_create_mode
Definition: file_perm.c:19
static bool do_sync
Definition: initdb.c:164
#define write(a, b, c)
Definition: win32.h:14
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:250
int64 pg_time_t
Definition: pgtime.h:23
pg_time_t time
Definition: pg_control.h:132
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
#define XLOG_CONTROL_FILE

References BasicOpenFile(), close, COMP_CRC32C, ControlFile, ControlFileData::crc, crc, DataDir, do_sync, ereport, errcode_for_file_access(), errmsg(), fd(), FIN_CRC32C, fsync, INIT_CRC32C, MAXPGPATH, PANIC, PG_BINARY, PG_CONTROL_FILE_SIZE, pg_fatal, pg_file_create_mode, pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), snprintf, ControlFileData::time, write, and XLOG_CONTROL_FILE.

Referenced by main(), modify_subscriber_sysid(), perform_rewind(), RewriteControlFile(), and UpdateControlFile().