From 45bbc66c47586243f10a535375496583d7c70030 Mon Sep 17 00:00:00 2001
From: Zsolt Parragi <zsolt.parragi@percona.com>
Date: Mon, 17 Aug 2026 11:52:53 +0000
Subject: [PATCH] Report single-page checksum failures in pg_stat_database

Base backups reported checksum failures to pg_stat_database only for
files with more than one failing page.  Commit 6b9e875f728 placed the
report inside the block emitting the per-file summary WARNING, which
is skipped for a single failure since the per-page WARNING already
covers it.  As a result, a backup failing on files with one corrupted
page each left checksum_failures untouched.

Fix by reporting the failures independently of the summary WARNING.
---
 src/backend/backup/basebackup.c              |  3 ++-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl | 17 +++++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c
index fe5ce23aaba..6a422b76932 100644
--- a/src/backend/backup/basebackup.c
+++ b/src/backend/backup/basebackup.c
@@ -1811,13 +1811,14 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
 	CloseTransientFile(fd);
 
 	if (checksum_failures > 1)
-	{
 		ereport(WARNING,
 				(errmsg_plural("file \"%s\" has a total of %d checksum verification failure",
 							   "file \"%s\" has a total of %d checksum verification failures",
 							   checksum_failures,
 							   readfilename, checksum_failures)));
 
+	if (checksum_failures > 0)
+	{
 		pgstat_prepare_report_checksum_failure(dboid);
 		pgstat_report_checksum_failures_in_db(dboid, checksum_failures);
 	}
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index cfcfdb8b580..b0d8b505dbd 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -913,6 +913,15 @@ $node->command_checks_all(
 	'pg_basebackup reports checksum mismatch');
 rmtree("$tempdir/backup_corrupt");
 
+# The failure must be counted in pg_stat_database even though the file only
+# has a single corrupted page.  The walsender reports the failures when it
+# exits, so poll for the counter.
+ok( $node->poll_query_until(
+		'postgres',
+		'SELECT checksum_failures = 1 FROM pg_stat_database '
+		  . "WHERE datname = 'postgres';"),
+	'checksum failure reported in pg_stat_database');
+
 # induce further corruption in 5 more blocks
 $node->stop;
 for my $i (1 .. 5)
@@ -942,6 +951,14 @@ $node->command_checks_all(
 	'pg_basebackup correctly report the total number of checksum mismatches');
 rmtree("$tempdir/backup_corrupt3");
 
+# The counter accumulates the failures of all three backups, including the
+# single-page failure of the second file in the last one.
+ok( $node->poll_query_until(
+		'postgres',
+		'SELECT checksum_failures = 14 FROM pg_stat_database '
+		  . "WHERE datname = 'postgres';"),
+	'checksum failures accumulated in pg_stat_database');
+
 # do not verify checksums, should return ok
 $node->command_ok(
 	[
-- 
2.54.0

