1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-03 00:26:59 +02:00

Retry reads of pg_control until checksum is valid.

On certain file systems (e.g. ext4) pg_control may appear torn if there is a concurrent write while reading the file. To prevent an invalid read, retry until the checksum matches the control data.

Special handling is required for the pg-version-force feature since the offset of the checksum is not known. In this case, scan from the default position to the end of the data looking for a checksum match. This is a bit imprecise, but better than nothing, and the chance of a random collision in the control data seems very remote considering the ratio of data size (< 512 bytes) to checksum size (4 bytes).

This was discovered and a possible solution proposed for PostgreSQL in [1]. The proposed solution may work for backup, but pgBackRest needs to be able to read pg_control reliably outside of backup. So no matter what fix is adopted for PostgreSQL, pgBackRest need retries. Further adjustment may be required as the PostgreSQL fix evolves.

[1] https://www.postgresql.org/message-id/20221123014224.xisi44byq3cf5psi%40awork3.anarazel.de
This commit is contained in:
David Steele
2023-09-10 09:47:49 -04:00
committed by GitHub
parent c1805134b3
commit f42d927d2d
21 changed files with 473 additions and 124 deletions

View File

@ -0,0 +1,21 @@
/***********************************************************************************************************************************
CRC-32 Calculation
CRC-32 and CRC-32C calculations required to validate the integrity of pg_control.
***********************************************************************************************************************************/
#ifndef POSTGRES_INTERFACE_CRC32_H
#define POSTGRES_INTERFACE_CRC32_H
#include <inttypes.h>
#include <stddef.h>
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Generate CRC-32 checksum (required by <= 9.4)
FN_EXTERN uint32_t crc32One(const unsigned char *data, size_t size);
// Generate CRC-32C checksum (required by >= 9.5)
FN_EXTERN uint32_t crc32cOne(const unsigned char *data, size_t size);
#endif