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)
 
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 {
55  int fd;
56  char ControlFilePath[MAXPGPATH];
57  pg_crc32c crc;
58  int r;
59 
60  AssertArg(crc_ok_p);
61 
63  snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
64 
65 #ifndef FRONTEND
66  if ((fd = OpenTransientFile(ControlFilePath, O_RDONLY | PG_BINARY)) == -1)
67  ereport(ERROR,
69  errmsg("could not open file \"%s\" for reading: %m",
70  ControlFilePath)));
71 #else
72  if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
73  {
74  pg_log_fatal("could not open file \"%s\" for reading: %m",
75  ControlFilePath);
77  }
78 #endif
79 
80  r = read(fd, ControlFile, sizeof(ControlFileData));
81  if (r != sizeof(ControlFileData))
82  {
83  if (r < 0)
84 #ifndef FRONTEND
85  ereport(ERROR,
87  errmsg("could not read file \"%s\": %m", ControlFilePath)));
88 #else
89  {
90  pg_log_fatal("could not read file \"%s\": %m", ControlFilePath);
92  }
93 #endif
94  else
95 #ifndef FRONTEND
96  ereport(ERROR,
98  errmsg("could not read file \"%s\": read %d of %zu",
99  ControlFilePath, r, sizeof(ControlFileData))));
100 #else
101  {
102  pg_log_fatal("could not read file \"%s\": read %d of %zu",
103  ControlFilePath, r, sizeof(ControlFileData));
105  }
106 #endif
107  }
108 
109 #ifndef FRONTEND
110  if (CloseTransientFile(fd) != 0)
111  ereport(ERROR,
113  errmsg("could not close file \"%s\": %m",
114  ControlFilePath)));
115 #else
116  if (close(fd) != 0)
117  {
118  pg_log_fatal("could not close file \"%s\": %m", ControlFilePath);
120  }
121 #endif
122 
123  /* Check the CRC. */
124  INIT_CRC32C(crc);
126  (char *) ControlFile,
128  FIN_CRC32C(crc);
129 
130  *crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
131 
132  /* Make sure the control file is valid byte order. */
133  if (ControlFile->pg_control_version % 65536 == 0 &&
134  ControlFile->pg_control_version / 65536 != 0)
135 #ifndef FRONTEND
136  elog(ERROR, _("byte ordering mismatch"));
137 #else
138  pg_log_warning("possible byte ordering mismatch\n"
139  "The byte ordering used to store the pg_control file might not match the one\n"
140  "used by this program. In that case the results below would be incorrect, and\n"
141  "the PostgreSQL installation would be incompatible with this data directory.");
142 #endif
143 
144  return ControlFile;
145 }
#define offsetof(type, field)
Definition: c.h:727
#define PG_BINARY
Definition: c.h:1268
#define AssertArg(condition)
Definition: c.h:806
int errcode_for_file_access(void)
Definition: elog.c:716
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define _(x)
Definition: elog.c:89
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
int CloseTransientFile(int fd)
Definition: fd.c:2688
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2511
char * DataDir
Definition: globals.c:65
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13
exit(1)
#define pg_log_fatal(...)
Definition: logging.h:76
void * palloc(Size size)
Definition: mcxt.c:1062
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:42
#define MAXPGPATH
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#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:94
return crc
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define snprintf
Definition: port.h:225
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define EXIT_FAILURE
Definition: settings.h:162
uint32 pg_control_version
Definition: pg_control.h:123
pg_crc32c crc
Definition: pg_control.h:232
static ControlFileData * ControlFile
Definition: xlog.c:750

References _, AssertArg, close, CloseTransientFile(), COMP_CRC32C, ControlFile, ControlFileData::crc, crc, DataDir, elog, EQ_CRC32C, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), ERROR, exit(), EXIT_FAILURE, fd(), FIN_CRC32C, INIT_CRC32C, MAXPGPATH, offsetof, OpenTransientFile(), palloc(), PG_BINARY, ControlFileData::pg_control_version, pg_log_fatal, pg_log_warning, read, and snprintf.

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

◆ update_controlfile()

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

Definition at line 157 of file controldata_utils.c.

159 {
160  int fd;
161  char buffer[PG_CONTROL_FILE_SIZE];
162  char ControlFilePath[MAXPGPATH];
163 
164  /*
165  * Apply the same static assertions as in backend's WriteControlFile().
166  */
168  "pg_control is too large for atomic disk writes");
170  "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
171 
172  /* Update timestamp */
173  ControlFile->time = (pg_time_t) time(NULL);
174 
175  /* Recalculate CRC of control file */
178  (char *) ControlFile,
181 
182  /*
183  * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
184  * the excess over sizeof(ControlFileData), to avoid premature EOF related
185  * errors when reading it.
186  */
187  memset(buffer, 0, PG_CONTROL_FILE_SIZE);
188  memcpy(buffer, ControlFile, sizeof(ControlFileData));
189 
190  snprintf(ControlFilePath, sizeof(ControlFilePath), "%s/%s", DataDir, XLOG_CONTROL_FILE);
191 
192 #ifndef FRONTEND
193 
194  /*
195  * All errors issue a PANIC, so no need to use OpenTransientFile() and to
196  * worry about file descriptor leaks.
197  */
198  if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY)) < 0)
199  ereport(PANIC,
201  errmsg("could not open file \"%s\": %m",
202  ControlFilePath)));
203 #else
204  if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
205  pg_file_create_mode)) == -1)
206  {
207  pg_log_fatal("could not open file \"%s\": %m", ControlFilePath);
209  }
210 #endif
211 
212  errno = 0;
213 #ifndef FRONTEND
215 #endif
217  {
218  /* if write didn't set errno, assume problem is no disk space */
219  if (errno == 0)
220  errno = ENOSPC;
221 
222 #ifndef FRONTEND
223  ereport(PANIC,
225  errmsg("could not write file \"%s\": %m",
226  ControlFilePath)));
227 #else
228  pg_log_fatal("could not write file \"%s\": %m", ControlFilePath);
230 #endif
231  }
232 #ifndef FRONTEND
234 #endif
235 
236  if (do_sync)
237  {
238 #ifndef FRONTEND
240  if (pg_fsync(fd) != 0)
241  ereport(PANIC,
243  errmsg("could not fsync file \"%s\": %m",
244  ControlFilePath)));
246 #else
247  if (fsync(fd) != 0)
248  {
249  pg_log_fatal("could not fsync file \"%s\": %m", ControlFilePath);
251  }
252 #endif
253  }
254 
255  if (close(fd) != 0)
256  {
257 #ifndef FRONTEND
258  ereport(PANIC,
260  errmsg("could not close file \"%s\": %m",
261  ControlFilePath)));
262 #else
263  pg_log_fatal("could not close file \"%s\": %m", ControlFilePath);
265 #endif
266  }
267 }
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:918
#define PANIC
Definition: elog.h:36
int BasicOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1071
int pg_fsync(int fd)
Definition: fd.c:359
int pg_file_create_mode
Definition: file_perm.c:19
static bool do_sync
Definition: initdb.c:144
#define write(a, b, c)
Definition: win32.h:14
#define PG_CONTROL_MAX_SAFE_SIZE
Definition: pg_control.h:241
#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:130
@ WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE
Definition: wait_event.h:167
@ WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE
Definition: wait_event.h:165
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:262
static void pgstat_report_wait_end(void)
Definition: wait_event.h:278
#define fsync(fd)
Definition: win32_port.h:76
#define XLOG_CONTROL_FILE

References BasicOpenFile(), close, COMP_CRC32C, ControlFile, ControlFileData::crc, crc, DataDir, do_sync, ereport, errcode_for_file_access(), errmsg(), exit(), EXIT_FAILURE, fd(), FIN_CRC32C, fsync, INIT_CRC32C, MAXPGPATH, offsetof, PANIC, PG_BINARY, PG_CONTROL_FILE_SIZE, PG_CONTROL_MAX_SAFE_SIZE, pg_file_create_mode, pg_fsync(), pg_log_fatal, pgstat_report_wait_end(), pgstat_report_wait_start(), snprintf, StaticAssertStmt, ControlFileData::time, WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE, WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE, write, and XLOG_CONTROL_FILE.

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