PostgreSQL Source Code  git master
controldata_utils.c File Reference
#include "postgres.h"
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.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 51 of file controldata_utils.c.

References _, AssertArg, close, CloseTransientFile(), COMP_CRC32C, ControlFile, elog, EQ_CRC32C, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), ERROR, EXIT_FAILURE, fd(), FIN_CRC32C, INIT_CRC32C, MAXPGPATH, offsetof, OpenTransientFile(), palloc(), PG_BINARY, 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().

52 {
54  int fd;
55  char ControlFilePath[MAXPGPATH];
56  pg_crc32c crc;
57  int r;
58 
59  AssertArg(crc_ok_p);
60 
61  ControlFile = palloc(sizeof(ControlFileData));
62  snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
63 
64 #ifndef FRONTEND
65  if ((fd = OpenTransientFile(ControlFilePath, O_RDONLY | PG_BINARY)) == -1)
66  ereport(ERROR,
68  errmsg("could not open file \"%s\" for reading: %m",
69  ControlFilePath)));
70 #else
71  if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
72  {
73  pg_log_fatal("could not open file \"%s\" for reading: %m",
74  ControlFilePath);
75  exit(EXIT_FAILURE);
76  }
77 #endif
78 
79  r = read(fd, ControlFile, sizeof(ControlFileData));
80  if (r != sizeof(ControlFileData))
81  {
82  if (r < 0)
83 #ifndef FRONTEND
84  ereport(ERROR,
86  errmsg("could not read file \"%s\": %m", ControlFilePath)));
87 #else
88  {
89  pg_log_fatal("could not read file \"%s\": %m", ControlFilePath);
90  exit(EXIT_FAILURE);
91  }
92 #endif
93  else
94 #ifndef FRONTEND
95  ereport(ERROR,
97  errmsg("could not read file \"%s\": read %d of %zu",
98  ControlFilePath, r, sizeof(ControlFileData))));
99 #else
100  {
101  pg_log_fatal("could not read file \"%s\": read %d of %zu",
102  ControlFilePath, r, sizeof(ControlFileData));
103  exit(EXIT_FAILURE);
104  }
105 #endif
106  }
107 
108 #ifndef FRONTEND
109  if (CloseTransientFile(fd) != 0)
110  ereport(ERROR,
112  errmsg("could not close file \"%s\": %m",
113  ControlFilePath)));
114 #else
115  if (close(fd) != 0)
116  {
117  pg_log_fatal("could not close file \"%s\": %m", ControlFilePath);
118  exit(EXIT_FAILURE);
119  }
120 #endif
121 
122  /* Check the CRC. */
123  INIT_CRC32C(crc);
124  COMP_CRC32C(crc,
125  (char *) ControlFile,
126  offsetof(ControlFileData, crc));
127  FIN_CRC32C(crc);
128 
129  *crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
130 
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)
134 #ifndef FRONTEND
135  elog(ERROR, _("byte ordering mismatch"));
136 #else
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.");
141 #endif
142 
143  return ControlFile;
144 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
uint32 pg_crc32c
Definition: pg_crc32c.h:38
int errcode(int sqlerrcode)
Definition: elog.c:570
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1191
#define ERROR
Definition: elog.h:43
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2255
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:593
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
#define ereport(elevel, rest)
Definition: elog.h:141
#define AssertArg(condition)
Definition: c.h:734
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:45
int CloseTransientFile(int fd)
Definition: fd.c:2432
static ControlFileData * ControlFile
Definition: xlog.c:721
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define EXIT_FAILURE
Definition: settings.h:154
char * DataDir
Definition: globals.c:62
#define close(a)
Definition: win32.h:12
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define snprintf
Definition: port.h:192
#define _(x)
Definition: elog.c:84
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:655
#define pg_log_fatal(...)
Definition: logging.h:75

◆ update_controlfile()

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

Definition at line 156 of file controldata_utils.c.

References BasicOpenFile(), close, COMP_CRC32C, ControlFileData::crc, ereport, errcode_for_file_access(), errmsg(), 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, WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE, WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE, write, and XLOG_CONTROL_FILE.

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

158 {
159  int fd;
160  char buffer[PG_CONTROL_FILE_SIZE];
161  char ControlFilePath[MAXPGPATH];
162 
163  /*
164  * Apply the same static assertions as in backend's WriteControlFile().
165  */
167  "pg_control is too large for atomic disk writes");
169  "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
170 
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);
177 
178  /*
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.
182  */
183  memset(buffer, 0, PG_CONTROL_FILE_SIZE);
184  memcpy(buffer, ControlFile, sizeof(ControlFileData));
185 
186  snprintf(ControlFilePath, sizeof(ControlFilePath), "%s/%s", DataDir, XLOG_CONTROL_FILE);
187 
188 #ifndef FRONTEND
189 
190  /*
191  * All errors issue a PANIC, so no need to use OpenTransientFile() and to
192  * worry about file descriptor leaks.
193  */
194  if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY)) < 0)
195  ereport(PANIC,
197  errmsg("could not open file \"%s\": %m",
198  ControlFilePath)));
199 #else
200  if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
201  pg_file_create_mode)) == -1)
202  {
203  pg_log_fatal("could not open file \"%s\": %m", ControlFilePath);
204  exit(EXIT_FAILURE);
205  }
206 #endif
207 
208  errno = 0;
209 #ifndef FRONTEND
211 #endif
212  if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
213  {
214  /* if write didn't set errno, assume problem is no disk space */
215  if (errno == 0)
216  errno = ENOSPC;
217 
218 #ifndef FRONTEND
219  ereport(PANIC,
221  errmsg("could not write file \"%s\": %m",
222  ControlFilePath)));
223 #else
224  pg_log_fatal("could not write file \"%s\": %m", ControlFilePath);
225  exit(EXIT_FAILURE);
226 #endif
227  }
228 #ifndef FRONTEND
230 #endif
231 
232  if (do_sync)
233  {
234 #ifndef FRONTEND
236  if (pg_fsync(fd) != 0)
237  ereport(PANIC,
239  errmsg("could not fsync file \"%s\": %m",
240  ControlFilePath)));
242 #else
243  if (fsync(fd) != 0)
244  {
245  pg_log_fatal("could not fsync file \"%s\": %m", ControlFilePath);
246  exit(EXIT_FAILURE);
247  }
248 #endif
249  }
250 
251  if (close(fd) != 0)
252  {
253 #ifndef FRONTEND
254  ereport(PANIC,
256  errmsg("could not close file \"%s\": %m",
257  ControlFilePath)));
258 #else
259  pg_log_fatal("could not close file \"%s\": %m", ControlFilePath);
260  exit(EXIT_FAILURE);
261 #endif
262  }
263 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
int pg_file_create_mode
Definition: file_perm.c:19
#define write(a, b, c)
Definition: win32.h:14
#define PG_CONTROL_MAX_SAFE_SIZE
Definition: pg_control.h:241
#define PANIC
Definition: elog.h:53
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1191
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:842
#define fsync(fd)
Definition: win32_port.h:63
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:593
pg_crc32c crc
Definition: pg_control.h:232
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
#define ereport(elevel, rest)
Definition: elog.h:141
#define XLOG_CONTROL_FILE
bool do_sync
Definition: pg_rewind.c:61
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:250
int BasicOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:944
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define EXIT_FAILURE
Definition: settings.h:154
char * DataDir
Definition: globals.c:62
int pg_fsync(int fd)
Definition: fd.c:331
#define close(a)
Definition: win32.h:12
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define snprintf
Definition: port.h:192
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define offsetof(type, field)
Definition: c.h:655
#define pg_log_fatal(...)
Definition: logging.h:75