mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Switch to CRC-32C in WAL and other places.
The old algorithm was found to not be the usual CRC-32 algorithm, used by Ethernet et al. We were using a non-reflected lookup table with code meant for a reflected lookup table. That's a strange combination that AFAICS does not correspond to any bit-wise CRC calculation, which makes it difficult to reason about its properties. Although it has worked well in practice, seems safer to use a well-known algorithm. Since we're changing the algorithm anyway, we might as well choose a different polynomial. The Castagnoli polynomial has better error-correcting properties than the traditional CRC-32 polynomial, even if we had implemented it correctly. Another reason for picking that is that some new CPUs have hardware support for calculating CRC-32C, but not CRC-32, let alone our strange variant of it. This patch doesn't add any support for such hardware, but a future patch could now do that. The old algorithm is kept around for tsquery and pg_trgm, which use the values in indexes that need to remain compatible so that pg_upgrade works. While we're at it, share the old lookup table for CRC-32 calculation between hstore, ltree and core. They all use the same table, so might as well.
This commit is contained in:
@ -1059,9 +1059,9 @@ begin:;
|
||||
* the whole record in the order: rdata, then backup blocks, then record
|
||||
* header.
|
||||
*/
|
||||
INIT_CRC32(rdata_crc);
|
||||
INIT_CRC32C(rdata_crc);
|
||||
for (rdt = rdata; rdt != NULL; rdt = rdt->next)
|
||||
COMP_CRC32(rdata_crc, rdt->data, rdt->len);
|
||||
COMP_CRC32C(rdata_crc, rdt->data, rdt->len);
|
||||
|
||||
/*
|
||||
* Construct record header (prev-link is filled in later, after reserving
|
||||
@ -1076,7 +1076,7 @@ begin:;
|
||||
rechdr->xl_info = info;
|
||||
rechdr->xl_rmid = rmid;
|
||||
rechdr->xl_prev = InvalidXLogRecPtr;
|
||||
COMP_CRC32(rdata_crc, ((char *) rechdr), offsetof(XLogRecord, xl_prev));
|
||||
COMP_CRC32C(rdata_crc, ((char *) rechdr), offsetof(XLogRecord, xl_prev));
|
||||
|
||||
hdr_rdt.next = rdata;
|
||||
hdr_rdt.data = (char *) rechdr;
|
||||
@ -1193,8 +1193,8 @@ begin:;
|
||||
* Now that xl_prev has been filled in, finish CRC calculation of the
|
||||
* record header.
|
||||
*/
|
||||
COMP_CRC32(rdata_crc, ((char *) &rechdr->xl_prev), sizeof(XLogRecPtr));
|
||||
FIN_CRC32(rdata_crc);
|
||||
COMP_CRC32C(rdata_crc, ((char *) &rechdr->xl_prev), sizeof(XLogRecPtr));
|
||||
FIN_CRC32C(rdata_crc);
|
||||
rechdr->xl_crc = rdata_crc;
|
||||
|
||||
/*
|
||||
@ -4344,11 +4344,11 @@ WriteControlFile(void)
|
||||
ControlFile->float8ByVal = FLOAT8PASSBYVAL;
|
||||
|
||||
/* Contents are protected with a CRC */
|
||||
INIT_CRC32(ControlFile->crc);
|
||||
COMP_CRC32(ControlFile->crc,
|
||||
(char *) ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32(ControlFile->crc);
|
||||
INIT_CRC32C(ControlFile->crc);
|
||||
COMP_CRC32C(ControlFile->crc,
|
||||
(char *) ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32C(ControlFile->crc);
|
||||
|
||||
/*
|
||||
* We write out PG_CONTROL_SIZE bytes into pg_control, zero-padding the
|
||||
@ -4444,13 +4444,13 @@ ReadControlFile(void)
|
||||
errhint("It looks like you need to initdb.")));
|
||||
|
||||
/* Now check the CRC. */
|
||||
INIT_CRC32(crc);
|
||||
COMP_CRC32(crc,
|
||||
(char *) ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32(crc);
|
||||
INIT_CRC32C(crc);
|
||||
COMP_CRC32C(crc,
|
||||
(char *) ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32C(crc);
|
||||
|
||||
if (!EQ_CRC32(crc, ControlFile->crc))
|
||||
if (!EQ_CRC32C(crc, ControlFile->crc))
|
||||
ereport(FATAL,
|
||||
(errmsg("incorrect checksum in control file")));
|
||||
|
||||
@ -4593,11 +4593,11 @@ UpdateControlFile(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
INIT_CRC32(ControlFile->crc);
|
||||
COMP_CRC32(ControlFile->crc,
|
||||
(char *) ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32(ControlFile->crc);
|
||||
INIT_CRC32C(ControlFile->crc);
|
||||
COMP_CRC32C(ControlFile->crc,
|
||||
(char *) ControlFile,
|
||||
offsetof(ControlFileData, crc));
|
||||
FIN_CRC32C(ControlFile->crc);
|
||||
|
||||
fd = BasicOpenFile(XLOG_CONTROL_FILE,
|
||||
O_RDWR | PG_BINARY,
|
||||
@ -4975,10 +4975,10 @@ BootStrapXLOG(void)
|
||||
record->xl_rmid = RM_XLOG_ID;
|
||||
memcpy(XLogRecGetData(record), &checkPoint, sizeof(checkPoint));
|
||||
|
||||
INIT_CRC32(crc);
|
||||
COMP_CRC32(crc, &checkPoint, sizeof(checkPoint));
|
||||
COMP_CRC32(crc, (char *) record, offsetof(XLogRecord, xl_crc));
|
||||
FIN_CRC32(crc);
|
||||
INIT_CRC32C(crc);
|
||||
COMP_CRC32C(crc, &checkPoint, sizeof(checkPoint));
|
||||
COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
|
||||
FIN_CRC32C(crc);
|
||||
record->xl_crc = crc;
|
||||
|
||||
/* Create first XLOG segment file */
|
||||
|
Reference in New Issue
Block a user