make_wal_records_use_page_checksums.v0.patch

application/octet-stream

Filename: make_wal_records_use_page_checksums.v0.patch
Type: application/octet-stream
Part: 0
Message: Re: Enabling Checksums

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v0
File+
src/backend/access/transam/xlog.c 33 12
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3cb866f..6689360 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -855,6 +855,22 @@ begin:;
 		elog(PANIC, "invalid xlog record length %u", len);
 
 	/*
+	 * Calculate CRC of the data but not the backup blocks.
+	 *
+	 * We calculate the checksum for each backup block separately, then
+	 * include the block checksum within the main checksum.
+	 *
+	 * Note that the record header isn't added into the CRC initially since we
+	 * don't know the prev-link yet.  Thus, the CRC will represent the CRC of
+	 * the whole record in the order: rdata, then record header.
+	 *
+	 * End result is that all data in the WAL record is covered by checksum.
+	 */
+	INIT_CRC32(rdata_crc);
+	for (rdt = rdata; rdt != NULL; rdt = rdt->next)
+		COMP_CRC32(rdata_crc, rdt->data, rdt->len);
+
+	/*
 	 * Make additional rdata chain entries for the backup blocks, so that we
 	 * don't need to special-case them in the write loop.  This modifies the
 	 * original rdata chain, but we keep a pointer to the last regular entry,
@@ -882,6 +898,23 @@ begin:;
 		bkpb = &(dtbuf_xlg[i]);
 		page = (char *) BufferGetBlock(dtbuf[i]);
 
+		/*
+		 * Set the checksum on each of the backup blocks. We do this instead
+		 * of including the backup blocks inside the main checksum. So the WAL
+		 * record is protected by a CRC32 check, while the backup blocks are
+		 * protected by a 16-bit checksum. We don't use the block number as
+		 * part of the checksum, so we leave that set at zero.
+		 *
+		 * Note that this is unconditional. We want every WAL record to be
+		 * covered by a checksum, even if page_checksum option is not enabled.
+		 * This calculation forms part of the WAL checksum.
+		 *
+		 * First field on each page is pd_lsn which is an XLogRecPtr, then we
+		 * have pd_checksum which is an uint16.
+		 */
+		PageSetChecksumInplace(page, 0);
+		COMP_CRC32(rdata_crc, page + sizeof(XLogRecPtr), sizeof(uint16));
+
 		rdt->next = &(dtbuf_rdt1[i]);
 		rdt = rdt->next;
 
@@ -917,18 +950,6 @@ begin:;
 	}
 
 	/*
-	 * Calculate CRC of the data, including all the backup blocks
-	 *
-	 * Note that the record header isn't added into the CRC initially since we
-	 * don't know the prev-link yet.  Thus, the CRC will represent the CRC of
-	 * the whole record in the order: rdata, then backup blocks, then record
-	 * header.
-	 */
-	INIT_CRC32(rdata_crc);
-	for (rdt = rdata; rdt != NULL; rdt = rdt->next)
-		COMP_CRC32(rdata_crc, rdt->data, rdt->len);
-
-	/*
 	 * Construct record header (prev-link and CRC are filled in later), and
 	 * make that the first chunk in the chain.
 	 */