Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * controldata_utils.c
4 : * Common code for control data file output.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2023, 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 :
28 : #include "access/xlog_internal.h"
29 : #include "catalog/pg_control.h"
30 : #include "common/controldata_utils.h"
31 : #include "common/file_perm.h"
32 : #ifdef FRONTEND
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 : */
51 : ControlFileData *
1469 peter 52 CBC 213 : get_controlfile(const char *DataDir, bool *crc_ok_p)
53 : {
54 : ControlFileData *ControlFile;
55 : int fd;
56 : char ControlFilePath[MAXPGPATH];
57 : pg_crc32c crc;
58 : int r;
59 :
163 peter 60 GNC 213 : Assert(crc_ok_p);
61 :
209 62 213 : ControlFile = palloc_object(ControlFileData);
2591 mail 63 CBC 213 : snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
64 :
65 : #ifndef FRONTEND
1501 66 12 : if ((fd = OpenTransientFile(ControlFilePath, O_RDONLY | PG_BINARY)) == -1)
2589 mail 67 UBC 0 : ereport(ERROR,
68 : (errcode_for_file_access(),
69 : errmsg("could not open file \"%s\" for reading: %m",
70 : ControlFilePath)));
71 : #else
1501 mail 72 CBC 201 : if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
366 tgl 73 1 : pg_fatal("could not open file \"%s\" for reading: %m",
74 : ControlFilePath);
75 : #endif
76 :
1787 magnus 77 212 : r = read(fd, ControlFile, sizeof(ControlFileData));
78 212 : if (r != sizeof(ControlFileData))
79 : {
1787 magnus 80 UBC 0 : if (r < 0)
81 : #ifndef FRONTEND
82 0 : ereport(ERROR,
83 : (errcode_for_file_access(),
84 : errmsg("could not read file \"%s\": %m", ControlFilePath)));
85 : #else
366 tgl 86 0 : pg_fatal("could not read file \"%s\": %m", ControlFilePath);
87 : #endif
88 : else
89 : #ifndef FRONTEND
1787 magnus 90 0 : ereport(ERROR,
91 : (errcode(ERRCODE_DATA_CORRUPTED),
92 : errmsg("could not read file \"%s\": read %d of %zu",
93 : ControlFilePath, r, sizeof(ControlFileData))));
94 : #else
366 tgl 95 0 : pg_fatal("could not read file \"%s\": read %d of %zu",
96 : ControlFilePath, r, sizeof(ControlFileData));
97 : #endif
98 : }
99 :
100 : #ifndef FRONTEND
1373 peter 101 CBC 12 : if (CloseTransientFile(fd) != 0)
1492 michael 102 UBC 0 : ereport(ERROR,
103 : (errcode_for_file_access(),
104 : errmsg("could not close file \"%s\": %m",
105 : ControlFilePath)));
106 : #else
1373 peter 107 CBC 200 : if (close(fd) != 0)
366 tgl 108 UBC 0 : pg_fatal("could not close file \"%s\": %m", ControlFilePath);
109 : #endif
110 :
111 : /* Check the CRC. */
2591 mail 112 CBC 212 : INIT_CRC32C(crc);
113 212 : COMP_CRC32C(crc,
114 : (char *) ControlFile,
115 : offsetof(ControlFileData, crc));
116 212 : FIN_CRC32C(crc);
117 :
2384 peter_e 118 212 : *crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
119 :
120 : /* Make sure the control file is valid byte order. */
2591 mail 121 212 : if (ControlFile->pg_control_version % 65536 == 0 &&
122 1 : ControlFile->pg_control_version / 65536 != 0)
123 : #ifndef FRONTEND
2591 mail 124 UBC 0 : elog(ERROR, _("byte ordering mismatch"));
125 : #else
1469 peter 126 0 : pg_log_warning("possible byte ordering mismatch\n"
127 : "The byte ordering used to store the pg_control file might not match the one\n"
128 : "used by this program. In that case the results below would be incorrect, and\n"
129 : "the PostgreSQL installation would be incompatible with this data directory.");
130 : #endif
131 :
2591 mail 132 CBC 212 : return ControlFile;
133 : }
134 :
135 : /*
136 : * update_controlfile()
137 : *
138 : * Update controlfile values with the contents given by caller. The
139 : * contents to write are included in "ControlFile". "do_sync" can be
140 : * optionally used to flush the updated control file. Note that it is up
141 : * to the caller to properly lock ControlFileLock when calling this
142 : * routine in the backend.
143 : */
144 : void
1469 peter 145 10931 : update_controlfile(const char *DataDir,
146 : ControlFileData *ControlFile, bool do_sync)
147 : {
148 : int fd;
149 : char buffer[PG_CONTROL_FILE_SIZE];
150 : char ControlFilePath[MAXPGPATH];
151 :
496 michael 152 ECB : /* Update timestamp */
496 michael 153 GIC 10931 : ControlFile->time = (pg_time_t) time(NULL);
154 :
155 : /* Recalculate CRC of control file */
1489 156 10931 : INIT_CRC32C(ControlFile->crc);
157 10931 : COMP_CRC32C(ControlFile->crc,
158 : (char *) ControlFile,
1489 michael 159 ECB : offsetof(ControlFileData, crc));
1489 michael 160 CBC 10931 : FIN_CRC32C(ControlFile->crc);
161 :
1489 michael 162 ECB : /*
163 : * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
164 : * the excess over sizeof(ControlFileData), to avoid premature EOF related
165 : * errors when reading it.
166 : */
1489 michael 167 GIC 10931 : memset(buffer, 0, PG_CONTROL_FILE_SIZE);
168 10931 : memcpy(buffer, ControlFile, sizeof(ControlFileData));
169 :
1489 michael 170 CBC 10931 : snprintf(ControlFilePath, sizeof(ControlFilePath), "%s/%s", DataDir, XLOG_CONTROL_FILE);
1489 michael 171 EUB :
172 : #ifndef FRONTEND
173 :
174 : /*
175 : * All errors issue a PANIC, so no need to use OpenTransientFile() and to
1483 michael 176 ECB : * worry about file descriptor leaks.
177 : */
1483 michael 178 GBC 10909 : if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY)) < 0)
1489 michael 179 UIC 0 : ereport(PANIC,
180 : (errcode_for_file_access(),
1489 michael 181 ECB : errmsg("could not open file \"%s\": %m",
182 : ControlFilePath)));
183 : #else
1489 michael 184 GIC 22 : if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
1489 michael 185 ECB : pg_file_create_mode)) == -1)
366 tgl 186 UIC 0 : pg_fatal("could not open file \"%s\": %m", ControlFilePath);
187 : #endif
1489 michael 188 EUB :
1489 michael 189 GBC 10931 : errno = 0;
190 : #ifndef FRONTEND
1483 michael 191 GIC 10909 : pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE);
1483 michael 192 EUB : #endif
1489 michael 193 GIC 10931 : if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
194 : {
195 : /* if write didn't set errno, assume problem is no disk space */
1489 michael 196 UIC 0 : if (errno == 0)
1489 michael 197 UBC 0 : errno = ENOSPC;
198 :
199 : #ifndef FRONTEND
1489 michael 200 UIC 0 : ereport(PANIC,
1489 michael 201 ECB : (errcode_for_file_access(),
202 : errmsg("could not write file \"%s\": %m",
203 : ControlFilePath)));
204 : #else
366 tgl 205 UIC 0 : pg_fatal("could not write file \"%s\": %m", ControlFilePath);
206 : #endif
1489 michael 207 ECB : }
1483 208 : #ifndef FRONTEND
1483 michael 209 GBC 10909 : pgstat_report_wait_end();
210 : #endif
211 :
1483 michael 212 GIC 10931 : if (do_sync)
1483 michael 213 ECB : {
214 : #ifndef FRONTEND
1483 michael 215 CBC 10909 : pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE);
1483 michael 216 GBC 10909 : if (pg_fsync(fd) != 0)
1483 michael 217 UIC 0 : ereport(PANIC,
218 : (errcode_for_file_access(),
219 : errmsg("could not fsync file \"%s\": %m",
1483 michael 220 ECB : ControlFilePath)));
1483 michael 221 GIC 10909 : pgstat_report_wait_end();
222 : #else
1483 michael 223 GBC 10 : if (fsync(fd) != 0)
366 tgl 224 UIC 0 : pg_fatal("could not fsync file \"%s\": %m", ControlFilePath);
225 : #endif
226 : }
227 :
1373 peter 228 GBC 10931 : if (close(fd) != 0)
229 : {
230 : #ifndef FRONTEND
1489 michael 231 LBC 0 : ereport(PANIC,
232 : (errcode_for_file_access(),
233 : errmsg("could not close file \"%s\": %m",
234 : ControlFilePath)));
235 : #else
366 tgl 236 UIC 0 : pg_fatal("could not close file \"%s\": %m", ControlFilePath);
237 : #endif
238 : }
1489 michael 239 GIC 10931 : }
|