reread.patch

text/plain

Filename: reread.patch
Type: text/plain
Part: 0
Message: Re: [PATCH] Verify Checksums during Basebackups

Patch

Format: unified
File+
src/backend/replication/basebackup.c 26 2
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 9f735a2c07..48bacfe5dd 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1258,6 +1258,7 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
 	int			i;
 	pgoff_t		len = 0;
 	char		page[BLCKSZ];
+	int			block_error = -1;
 	size_t		pad;
 	PageHeader  phdr;
 	int			segmentno = 0;
@@ -1328,9 +1329,16 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
 				verify_checksum = false;
 				continue;
 			}
-			for (i = 0; i < cnt / BLCKSZ; i++)
+
+			/*
+			 * Validate all blocks in the buffer.  If checking after the buffer
+			 * was reread then start at the block that caused the reread.
+             */
+			for (i = block_error == -1 ? 0 : block_error; i < cnt / BLCKSZ; i++)
 			{
+				blkno = len / BLCKSZ + i;
 				memcpy(page, (buf + BLCKSZ * i), BLCKSZ);
+
 				/*
 				 * Only check pages which have not been modified since the
 				 * start of the base backup.
@@ -1341,6 +1349,18 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
 					phdr = (PageHeader) page;
 					if (phdr->pd_checksum != checksum)
 					{
+						/*
+						 * If first time encountering an error on this block
+						 * then read the last buffer again to see if the
+						 * checksum is corrected.
+						 */
+						if (block_error == -1)
+						{
+							block_error = i;
+							fseek(fp, -cnt, SEEK_CUR);
+							break;
+						}
+
 						ereport(WARNING,
 								(errmsg("checksum verification failed in file "
 										"\"%s\", block %d: calculated %X but "
@@ -1350,8 +1370,12 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
 						checksum_failure = true;
 					}
 				}
-				blkno++;
+				block_error = -1;
 			}
+
+			/* Read the buffer again if there were checksum errors */
+			if (block_error != -1)
+				continue;
 		}
 
 		/* Send the chunk as a CopyData message */