mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Fix CRC check handling in get_controlfile
The previous patch broke this by returning NULL for a failed CRC check, which pg_controldata would then try to read. Fix by returning the result of the CRC check in a separate argument. Michael Paquier and myself
This commit is contained in:
@ -34,6 +34,7 @@ pg_control_system(PG_FUNCTION_ARGS)
|
|||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
HeapTuple htup;
|
HeapTuple htup;
|
||||||
ControlFileData *ControlFile;
|
ControlFileData *ControlFile;
|
||||||
|
bool crc_ok;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a tuple descriptor for the result row. This must match this
|
* Construct a tuple descriptor for the result row. This must match this
|
||||||
@ -51,8 +52,8 @@ pg_control_system(PG_FUNCTION_ARGS)
|
|||||||
tupdesc = BlessTupleDesc(tupdesc);
|
tupdesc = BlessTupleDesc(tupdesc);
|
||||||
|
|
||||||
/* read the control file */
|
/* read the control file */
|
||||||
ControlFile = get_controlfile(DataDir, NULL);
|
ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
|
||||||
if (!ControlFile)
|
if (!crc_ok)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errmsg("calculated CRC checksum does not match value stored in file")));
|
(errmsg("calculated CRC checksum does not match value stored in file")));
|
||||||
|
|
||||||
@ -83,6 +84,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
|
|||||||
ControlFileData *ControlFile;
|
ControlFileData *ControlFile;
|
||||||
XLogSegNo segno;
|
XLogSegNo segno;
|
||||||
char xlogfilename[MAXFNAMELEN];
|
char xlogfilename[MAXFNAMELEN];
|
||||||
|
bool crc_ok;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a tuple descriptor for the result row. This must match this
|
* Construct a tuple descriptor for the result row. This must match this
|
||||||
@ -130,8 +132,8 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
|
|||||||
tupdesc = BlessTupleDesc(tupdesc);
|
tupdesc = BlessTupleDesc(tupdesc);
|
||||||
|
|
||||||
/* Read the control file. */
|
/* Read the control file. */
|
||||||
ControlFile = get_controlfile(DataDir, NULL);
|
ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
|
||||||
if (!ControlFile)
|
if (!crc_ok)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errmsg("calculated CRC checksum does not match value stored in file")));
|
(errmsg("calculated CRC checksum does not match value stored in file")));
|
||||||
|
|
||||||
@ -216,6 +218,7 @@ pg_control_recovery(PG_FUNCTION_ARGS)
|
|||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
HeapTuple htup;
|
HeapTuple htup;
|
||||||
ControlFileData *ControlFile;
|
ControlFileData *ControlFile;
|
||||||
|
bool crc_ok;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a tuple descriptor for the result row. This must match this
|
* Construct a tuple descriptor for the result row. This must match this
|
||||||
@ -235,8 +238,8 @@ pg_control_recovery(PG_FUNCTION_ARGS)
|
|||||||
tupdesc = BlessTupleDesc(tupdesc);
|
tupdesc = BlessTupleDesc(tupdesc);
|
||||||
|
|
||||||
/* read the control file */
|
/* read the control file */
|
||||||
ControlFile = get_controlfile(DataDir, NULL);
|
ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
|
||||||
if (!ControlFile)
|
if (!crc_ok)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errmsg("calculated CRC checksum does not match value stored in file")));
|
(errmsg("calculated CRC checksum does not match value stored in file")));
|
||||||
|
|
||||||
@ -268,6 +271,7 @@ pg_control_init(PG_FUNCTION_ARGS)
|
|||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
HeapTuple htup;
|
HeapTuple htup;
|
||||||
ControlFileData *ControlFile;
|
ControlFileData *ControlFile;
|
||||||
|
bool crc_ok;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a tuple descriptor for the result row. This must match this
|
* Construct a tuple descriptor for the result row. This must match this
|
||||||
@ -303,8 +307,8 @@ pg_control_init(PG_FUNCTION_ARGS)
|
|||||||
tupdesc = BlessTupleDesc(tupdesc);
|
tupdesc = BlessTupleDesc(tupdesc);
|
||||||
|
|
||||||
/* read the control file */
|
/* read the control file */
|
||||||
ControlFile = get_controlfile(DataDir, NULL);
|
ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
|
||||||
if (!ControlFile)
|
if (!crc_ok)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errmsg("calculated CRC checksum does not match value stored in file")));
|
(errmsg("calculated CRC checksum does not match value stored in file")));
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ int
|
|||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ControlFileData *ControlFile;
|
ControlFileData *ControlFile;
|
||||||
|
bool crc_ok;
|
||||||
char *DataDir = NULL;
|
char *DataDir = NULL;
|
||||||
time_t time_tmp;
|
time_t time_tmp;
|
||||||
char pgctime_str[128];
|
char pgctime_str[128];
|
||||||
@ -155,8 +156,8 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get a copy of the control file */
|
/* get a copy of the control file */
|
||||||
ControlFile = get_controlfile(DataDir, progname);
|
ControlFile = get_controlfile(DataDir, progname, &crc_ok);
|
||||||
if (!ControlFile)
|
if (!crc_ok)
|
||||||
printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
|
printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
|
||||||
"Either the file is corrupt, or it has a different layout than this program\n"
|
"Either the file is corrupt, or it has a different layout than this program\n"
|
||||||
"is expecting. The results below are untrustworthy.\n\n"));
|
"is expecting. The results below are untrustworthy.\n\n"));
|
||||||
|
@ -2147,28 +2147,18 @@ static DBState
|
|||||||
get_control_dbstate(void)
|
get_control_dbstate(void)
|
||||||
{
|
{
|
||||||
DBState ret;
|
DBState ret;
|
||||||
|
bool crc_ok;
|
||||||
|
ControlFileData *control_file_data = get_controlfile(pg_data, progname, &crc_ok);
|
||||||
|
|
||||||
for (;;)
|
if (!crc_ok)
|
||||||
{
|
{
|
||||||
ControlFileData *control_file_data = get_controlfile(pg_data, progname);
|
|
||||||
|
|
||||||
if (control_file_data)
|
|
||||||
{
|
|
||||||
ret = control_file_data->state;
|
|
||||||
pfree(control_file_data);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wait_seconds > 0)
|
|
||||||
{
|
|
||||||
pg_usleep(1000000); /* 1 sec */
|
|
||||||
wait_seconds--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_stderr(_("%s: control file appears to be corrupt\n"), progname);
|
write_stderr(_("%s: control file appears to be corrupt\n"), progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = control_file_data->state;
|
||||||
|
pfree(control_file_data);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,21 +29,24 @@
|
|||||||
#include "port/pg_crc32c.h"
|
#include "port/pg_crc32c.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_controlfile(char *DataDir, const char *progname)
|
* get_controlfile(char *DataDir, const char *progname, bool *crc_ok_p)
|
||||||
*
|
*
|
||||||
* Get controlfile values. The caller is responsible
|
* Get controlfile values. The result is returned as a palloc'd copy of the
|
||||||
* for pfreeing the result.
|
* control file data.
|
||||||
*
|
*
|
||||||
* Returns NULL if the CRC did not match.
|
* crc_ok_p can be used by the caller to see whether the CRC of the control
|
||||||
|
* file data is correct.
|
||||||
*/
|
*/
|
||||||
ControlFileData *
|
ControlFileData *
|
||||||
get_controlfile(const char *DataDir, const char *progname)
|
get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p)
|
||||||
{
|
{
|
||||||
ControlFileData *ControlFile;
|
ControlFileData *ControlFile;
|
||||||
int fd;
|
int fd;
|
||||||
char ControlFilePath[MAXPGPATH];
|
char ControlFilePath[MAXPGPATH];
|
||||||
pg_crc32c crc;
|
pg_crc32c crc;
|
||||||
|
|
||||||
|
AssertArg(crc_ok_p);
|
||||||
|
|
||||||
ControlFile = palloc(sizeof(ControlFileData));
|
ControlFile = palloc(sizeof(ControlFileData));
|
||||||
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
|
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
|
||||||
|
|
||||||
@ -83,11 +86,7 @@ get_controlfile(const char *DataDir, const char *progname)
|
|||||||
offsetof(ControlFileData, crc));
|
offsetof(ControlFileData, crc));
|
||||||
FIN_CRC32C(crc);
|
FIN_CRC32C(crc);
|
||||||
|
|
||||||
if (!EQ_CRC32C(crc, ControlFile->crc))
|
*crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
|
||||||
{
|
|
||||||
pfree(ControlFile);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the control file is valid byte order. */
|
/* Make sure the control file is valid byte order. */
|
||||||
if (ControlFile->pg_control_version % 65536 == 0 &&
|
if (ControlFile->pg_control_version % 65536 == 0 &&
|
||||||
|
@ -12,6 +12,6 @@
|
|||||||
|
|
||||||
#include "catalog/pg_control.h"
|
#include "catalog/pg_control.h"
|
||||||
|
|
||||||
extern ControlFileData *get_controlfile(const char *DataDir, const char *progname);
|
extern ControlFileData *get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p);
|
||||||
|
|
||||||
#endif /* COMMON_CONTROLDATA_UTILS_H */
|
#endif /* COMMON_CONTROLDATA_UTILS_H */
|
||||||
|
Reference in New Issue
Block a user