From c9c28752032900150244110ad4fea87abad57e1f Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Wed, 29 Jul 2026 14:13:28 +0000
Subject: [PATCH v4 3/6] pgstat: move WAL statistics to new per-backend
 infrastructure

PGSTAT_KIND_BACKEND stores each backend's WAL, lock, and I/O statistics
together in one variable-numbered entry keyed by ProcNumber. Move WAL
statistics into a dedicated fixed array associated with the WAL statistics
kind and indexed by ProcNumber. The global WAL stats hold data for backends
that have exited, while the array holds statistics for active backends.

Build pg_stat_wal snapshots by copying the global stats and adding every
active per-backend entry.

Transfer the current process's entry into the global stats before invalidating
it at process exit or ProcNumber reuse. Transfer all entries before a clean
shutdown writes the statistics file.

Remove WAL counters from PGSTAT_KIND_BACKEND and use the new infrastructure
in pg_stat_get_backend_wal(). This also makes WAL statistics available for
auxiliary and shared-memory-only workers. Update the documentation to
describe the new behavior.

Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/anCjoFkGah/uB7lw%40bdtpg
---
 doc/src/sgml/monitoring.sgml                |   7 +-
 src/backend/utils/activity/pgstat.c         |  18 +++
 src/backend/utils/activity/pgstat_backend.c |  75 ---------
 src/backend/utils/activity/pgstat_wal.c     | 168 +++++++++++++++++---
 src/backend/utils/adt/pgstatfuncs.c         |  37 ++++-
 src/include/pgstat.h                        |   3 +-
 src/include/utils/pgstat_internal.h         |  21 ++-
 src/tools/pgindent/typedefs.list            |   1 +
 8 files changed, 218 insertions(+), 112 deletions(-)
   3.6% doc/src/sgml/
  77.6% src/backend/utils/activity/
  10.3% src/backend/utils/adt/
   6.3% src/include/utils/

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 31ff4a9d99f..f52b859c141 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5868,10 +5868,6 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         Returns WAL statistics about the backend with the specified
         process ID. The output fields are exactly the same as the ones in the
         <structname>pg_stat_wal</structname> view.
-       </para>
-       <para>
-        The function does not return WAL statistics for the checkpointer,
-        the background writer, the startup process and the autovacuum launcher.
        </para></entry>
       </row>
 
@@ -6047,7 +6043,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         <listitem>
          <para>
           <literal>wal</literal>: Reset all the counters shown in the
-          <structname>pg_stat_wal</structname> view.
+          <structname>pg_stat_wal</structname> view, as well as per-backend
+          WAL statistics returned by <function>pg_stat_get_backend_wal</function>.
          </para>
         </listitem>
         <listitem>
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 3dd03a71bba..9ea09243ccc 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -514,6 +514,11 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
 		.init_shmem_cb = pgstat_wal_init_shmem_cb,
 		.reset_all_cb = pgstat_wal_reset_all_cb,
 		.snapshot_cb = pgstat_wal_snapshot_cb,
+
+		.per_backend_entry_size = sizeof(PgStatShared_WalBackendEntry),
+		.per_backend_data_off = offsetof(PgStatShared_WalBackendEntry, stats),
+		.per_backend_data_len = sizeof(PgStat_WalStats),
+		.per_backend_acc_cb = pgstat_wal_per_backend_acc_cb,
 	},
 };
 
@@ -625,6 +630,9 @@ pgstat_before_server_shutdown(int code, Datum arg)
 	 */
 	if (code == 0)
 	{
+		/* Transfer all live per-backend stats before writing the stats file */
+		pgstat_wal_acc_all_backends();
+
 		pgStatLocal.shmem->is_shutdown = true;
 		pgstat_write_statsfile();
 	}
@@ -668,6 +676,9 @@ pgstat_shutdown_hook(int code, Datum arg)
 	if (!pgstat_drop_entry(PGSTAT_KIND_BACKEND, InvalidOid, MyProcNumber, false))
 		pgstat_request_entry_refs_gc();
 
+	/* Accumulate per-backend WAL stats into the global stats */
+	pgstat_wal_acc_backend_cb();
+
 	pgstat_detach_shmem();
 
 #ifdef USE_ASSERT_CHECKING
@@ -688,6 +699,13 @@ pgstat_initialize(void)
 
 	pgstat_attach_shmem();
 
+	/*
+	 * A previous process may have left statistics in entries for this reused
+	 * ProcNumber. Transfer them to the global statistics before activating
+	 * the current process's entries.
+	 */
+	pgstat_wal_acc_backend_cb();
+
 	/*
 	 * Activate per-backend statistics entries here. This also covers
 	 * processes that never call InitPostgres(), such as shared-memory-only
diff --git a/src/backend/utils/activity/pgstat_backend.c b/src/backend/utils/activity/pgstat_backend.c
index b736b2ccc6f..76b970a8c41 100644
--- a/src/backend/utils/activity/pgstat_backend.c
+++ b/src/backend/utils/activity/pgstat_backend.c
@@ -41,14 +41,6 @@ static PgStat_BackendPending PendingBackendStats;
 static bool backend_has_iostats = false;
 static bool backend_has_lockstats = false;
 
-/*
- * WAL usage counters saved from pgWalUsage at the previous call to
- * pgstat_flush_backend().  This is used to calculate how much WAL usage
- * happens between pgstat_flush_backend() calls, by subtracting the
- * previous counters from the current ones.
- */
-static WalUsage prevBackendWalUsage;
-
 /*
  * Utility routines to report I/O stats for backends, kept here to avoid
  * exposing PendingBackendStats to the outside world.
@@ -244,58 +236,6 @@ pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref)
 	backend_has_iostats = false;
 }
 
-/*
- * To determine whether WAL usage happened.
- */
-static inline bool
-pgstat_backend_wal_have_pending(void)
-{
-	return (pgWalUsage.wal_records != prevBackendWalUsage.wal_records);
-}
-
-/*
- * Flush out locally pending backend WAL statistics.  Locking is managed
- * by the caller.
- */
-static void
-pgstat_flush_backend_entry_wal(PgStat_EntryRef *entry_ref)
-{
-	PgStatShared_Backend *shbackendent;
-	PgStat_WalCounters *bktype_shstats;
-	WalUsage	wal_usage_diff = {0};
-
-	/*
-	 * This function can be called even if nothing at all has happened for WAL
-	 * statistics.  In this case, avoid unnecessarily modifying the stats
-	 * entry.
-	 */
-	if (!pgstat_backend_wal_have_pending())
-		return;
-
-	shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats;
-	bktype_shstats = &shbackendent->stats.wal_counters;
-
-	/*
-	 * Calculate how much WAL usage counters were increased by subtracting the
-	 * previous counters from the current ones.
-	 */
-	WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevBackendWalUsage);
-
-#define WALSTAT_ACC(fld, var_to_add) \
-	(bktype_shstats->fld += var_to_add.fld)
-	WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
-	WALSTAT_ACC(wal_records, wal_usage_diff);
-	WALSTAT_ACC(wal_fpi, wal_usage_diff);
-	WALSTAT_ACC(wal_bytes, wal_usage_diff);
-	WALSTAT_ACC(wal_fpi_bytes, wal_usage_diff);
-#undef WALSTAT_ACC
-
-	/*
-	 * Save the current counters for the subsequent calculation of WAL usage.
-	 */
-	prevBackendWalUsage = pgWalUsage;
-}
-
 /*
  * Flush out locally pending backend lock statistics.  Locking is managed
  * by the caller.
@@ -345,11 +285,6 @@ pgstat_flush_backend(bool nowait, uint32 flags)
 	if ((flags & PGSTAT_BACKEND_FLUSH_IO) && backend_has_iostats)
 		has_pending_data = true;
 
-	/* Some WAL data pending? */
-	if ((flags & PGSTAT_BACKEND_FLUSH_WAL) &&
-		pgstat_backend_wal_have_pending())
-		has_pending_data = true;
-
 	/* Some lock data pending? */
 	if ((flags & PGSTAT_BACKEND_FLUSH_LOCK) && backend_has_lockstats)
 		has_pending_data = true;
@@ -366,9 +301,6 @@ pgstat_flush_backend(bool nowait, uint32 flags)
 	if (flags & PGSTAT_BACKEND_FLUSH_IO)
 		pgstat_flush_backend_entry_io(entry_ref);
 
-	if (flags & PGSTAT_BACKEND_FLUSH_WAL)
-		pgstat_flush_backend_entry_wal(entry_ref);
-
 	if (flags & PGSTAT_BACKEND_FLUSH_LOCK)
 		pgstat_flush_backend_entry_lock(entry_ref);
 
@@ -411,13 +343,6 @@ pgstat_create_backend(ProcNumber procnum)
 	MemSet(&PendingBackendStats, 0, sizeof(PgStat_BackendPending));
 	backend_has_iostats = false;
 	backend_has_lockstats = false;
-
-	/*
-	 * Initialize prevBackendWalUsage with pgWalUsage so that
-	 * pgstat_backend_flush_cb() can calculate how much pgWalUsage counters
-	 * are increased by subtracting prevBackendWalUsage from pgWalUsage.
-	 */
-	prevBackendWalUsage = pgWalUsage;
 }
 
 /*
diff --git a/src/backend/utils/activity/pgstat_wal.c b/src/backend/utils/activity/pgstat_wal.c
index 183e0a7a97b..8009ac38801 100644
--- a/src/backend/utils/activity/pgstat_wal.c
+++ b/src/backend/utils/activity/pgstat_wal.c
@@ -8,6 +8,11 @@
  * storage implementation and the details about individual types of
  * statistics.
  *
+ * WAL statistics use a per-backend array to avoid double-counting. Each
+ * backend flushes WAL usage to its own ProcNumber-indexed entry. The global
+ * pg_stat_wal view aggregates the global stats (which holds stats from exited
+ * backends) plus all active per-backend entries.
+ *
  * Copyright (c) 2001-2026, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
@@ -52,7 +57,6 @@ pgstat_report_wal(bool force)
 
 	/* flush wal stats */
 	(void) pgstat_wal_flush_cb(nowait);
-	pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_WAL);
 
 	/* flush IO stats */
 	pgstat_flush_io(nowait);
@@ -81,8 +85,8 @@ pgstat_wal_have_pending(void)
 }
 
 /*
- * Calculate how much WAL usage counters have increased by subtracting the
- * previous counters from the current ones.
+ * Flush WAL usage accumulated since the previous call to this process's
+ * per-backend entry.
  *
  * If nowait is true, this function returns true if the lock could not be
  * acquired. Otherwise return false.
@@ -90,7 +94,7 @@ pgstat_wal_have_pending(void)
 bool
 pgstat_wal_flush_cb(bool nowait)
 {
-	PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
+	PgStatShared_WalBackendEntry *entry;
 	WalUsage	wal_usage_diff = {0};
 
 	Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
@@ -105,19 +109,18 @@ pgstat_wal_flush_cb(bool nowait)
 		return false;
 
 	/*
-	 * We don't update the WAL usage portion of the local WalStats elsewhere.
 	 * Calculate how much WAL usage counters were increased by subtracting the
 	 * previous counters from the current ones.
 	 */
 	WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevWalUsage);
 
-	if (!nowait)
-		LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
-	else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
-		return true;
+	entry = pgstat_lock_my_per_backend_entry(PGSTAT_KIND_WAL, nowait);
+
+	if (entry == NULL)
+		return nowait;
 
 #define WALSTAT_ACC(fld, var_to_add) \
-	(stats_shmem->stats.wal_counters.fld += var_to_add.fld)
+	(entry->stats.wal_counters.fld += var_to_add.fld)
 	WALSTAT_ACC(wal_records, wal_usage_diff);
 	WALSTAT_ACC(wal_fpi, wal_usage_diff);
 	WALSTAT_ACC(wal_bytes, wal_usage_diff);
@@ -125,7 +128,7 @@ pgstat_wal_flush_cb(bool nowait)
 	WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
 #undef WALSTAT_ACC
 
-	LWLockRelease(&stats_shmem->lock);
+	LWLockRelease(&entry->header.lock);
 
 	/*
 	 * Save the current counters for the subsequent calculation of WAL usage.
@@ -157,21 +160,144 @@ pgstat_wal_init_shmem_cb(void *stats)
 void
 pgstat_wal_reset_all_cb(TimestampTz ts)
 {
-	PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
+	PgStatShared_Wal *shmem = &pgStatLocal.shmem->wal;
+
+	/*
+	 * Hold the kind lock while resetting both the global stats and active
+	 * entries. Transfers hold the same lock, so pre-reset counters cannot be
+	 * moved into the global stats after it is reset.
+	 */
+	LWLockAcquire(&shmem->lock, LW_EXCLUSIVE);
+	memset(&shmem->stats, 0, sizeof(shmem->stats));
+	shmem->stats.stat_reset_timestamp = ts;
+
+	/* Reset all per-backend entries */
+	for (ProcNumber procnum = 0; procnum < NumPerBackendStatSlots; procnum++)
+	{
+		PgStatShared_WalBackendEntry *entry;
+
+		entry = pgstat_get_per_backend_entry(PGSTAT_KIND_WAL, procnum);
 
-	LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
-	memset(&stats_shmem->stats, 0, sizeof(stats_shmem->stats));
-	stats_shmem->stats.stat_reset_timestamp = ts;
-	LWLockRelease(&stats_shmem->lock);
+		LWLockAcquire(&entry->header.lock, LW_EXCLUSIVE);
+		if (entry->header.backend_type != B_INVALID)
+		{
+			memset(&entry->stats.wal_counters, 0, sizeof(PgStat_WalCounters));
+			entry->stats.stat_reset_timestamp = ts;
+		}
+		LWLockRelease(&entry->header.lock);
+	}
+
+	LWLockRelease(&shmem->lock);
 }
 
+/*
+ * Build WAL stats snapshot by aggregating global stats and all live
+ * per-backend entries.
+ */
 void
 pgstat_wal_snapshot_cb(void)
 {
-	PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
+	PgStatShared_Wal *shmem = &pgStatLocal.shmem->wal;
+	PgStat_WalStats *snap = &pgStatLocal.snapshot.wal;
+
+	/*
+	 * Prevent entries from moving to the global stats between copying it and
+	 * scanning the per-backend array.
+	 */
+	LWLockAcquire(&shmem->lock, LW_SHARED);
+	memcpy(snap, &shmem->stats, sizeof(PgStat_WalStats));
+
+	/* Add in all active per-backend entries */
+	pgstat_per_backend_snapshot(PGSTAT_KIND_WAL, snap);
 
-	LWLockAcquire(&stats_shmem->lock, LW_SHARED);
-	memcpy(&pgStatLocal.snapshot.wal, &stats_shmem->stats,
-		   sizeof(pgStatLocal.snapshot.wal));
-	LWLockRelease(&stats_shmem->lock);
+	LWLockRelease(&shmem->lock);
+}
+
+#define WAL_ACCUMULATE_COUNTERS(dst, src) \
+do { \
+	(dst).wal_records += (src).wal_records; \
+	(dst).wal_fpi += (src).wal_fpi; \
+	(dst).wal_bytes += (src).wal_bytes; \
+	(dst).wal_fpi_bytes += (src).wal_fpi_bytes; \
+	(dst).wal_buffers_full += (src).wal_buffers_full; \
+} while (0)
+
+/*
+ * Accumulate one per-backend WAL entry into a snapshot or the global stats.
+ */
+void
+pgstat_wal_per_backend_acc_cb(void *dst, void *entry)
+{
+	PgStat_WalStats *stats = dst;
+	PgStatShared_WalBackendEntry *e = (PgStatShared_WalBackendEntry *) entry;
+
+	WAL_ACCUMULATE_COUNTERS(stats->wal_counters, e->stats.wal_counters);
+}
+
+/*
+ * Accumulate a backend's WAL stats into the global stats, then invalidate the
+ * entry.
+ *
+ * Called at backend exit after the final flush, or when a ProcNumber is
+ * being reused.
+ */
+void
+pgstat_wal_acc_backend_cb(void)
+{
+	pgstat_acc_my_per_backend(PGSTAT_KIND_WAL, &pgStatLocal.shmem->wal.lock);
+}
+
+/*
+ * Returns per-backend WAL statistics for the given ProcNumber.
+ */
+PgStat_WalStats *
+pgstat_fetch_stat_backend_wal(ProcNumber procnum)
+{
+	return (PgStat_WalStats *) pgstat_fetch_per_backend(PGSTAT_KIND_WAL, procnum);
+}
+
+/*
+ * Reset a backend's WAL stats. Accumulate the entry's counters into the
+ * global stats, then zero the stats and set the reset timestamp.
+ */
+void
+pgstat_wal_reset_backend_cb(ProcNumber procnum, TimestampTz ts)
+{
+	PgStatShared_Wal *shmem = &pgStatLocal.shmem->wal;
+	PgStatShared_WalBackendEntry *entry;
+
+	entry = pgstat_get_per_backend_entry(PGSTAT_KIND_WAL, procnum);
+	if (entry == NULL)
+		return;
+
+	LWLockAcquire(&shmem->lock, LW_EXCLUSIVE);
+	LWLockAcquire(&entry->header.lock, LW_EXCLUSIVE);
+
+	if (entry->header.backend_type == B_INVALID)
+	{
+		LWLockRelease(&entry->header.lock);
+		LWLockRelease(&shmem->lock);
+		return;
+	}
+
+	/* Accumulate current stats into global before zeroing */
+	WAL_ACCUMULATE_COUNTERS(shmem->stats.wal_counters, entry->stats.wal_counters);
+
+	/* Zero stats and set reset timestamp */
+	memset(&entry->stats.wal_counters, 0, sizeof(PgStat_WalCounters));
+	entry->stats.stat_reset_timestamp = ts;
+
+	LWLockRelease(&entry->header.lock);
+	LWLockRelease(&shmem->lock);
+}
+
+/*
+ * Accumulate all per-backend WAL stats entries into the global stats and
+ * invalidate them. Called at clean server shutdown to ensure all flushed data
+ * is preserved in the stats file.
+ */
+void
+pgstat_wal_acc_all_backends(void)
+{
+	pgstat_acc_all_per_backend(PGSTAT_KIND_WAL, &pgStatLocal.shmem->wal.lock);
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 64b6f60516c..ef541205db4 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1769,19 +1769,33 @@ Datum
 pg_stat_get_backend_wal(PG_FUNCTION_ARGS)
 {
 	int			pid;
-	PgStat_Backend *backend_stats;
-	PgStat_WalCounters bktype_stats;
+	PGPROC	   *proc;
+	ProcNumber	procnum;
+	PgBackendStatus *beentry;
+	PgStat_WalStats *wal_stats;
 
 	pid = PG_GETARG_INT32(0);
-	backend_stats = pgstat_fetch_stat_backend_by_pid(pid, NULL);
 
-	if (!backend_stats)
+	proc = BackendPidGetProc(pid);
+
+	if (!proc)
+		proc = AuxiliaryPidGetProc(pid);
+	if (!proc)
+		PG_RETURN_NULL();
+
+	procnum = GetNumberFromPGProc(proc);
+	beentry = pgstat_get_beentry_by_proc_number(procnum);
+
+	if (!beentry || beentry->st_procpid != pid)
 		PG_RETURN_NULL();
 
-	bktype_stats = backend_stats->wal_counters;
+	wal_stats = pgstat_fetch_stat_backend_wal(procnum);
 
-	/* save tuples with data from this PgStat_WalCounters */
-	return (pg_stat_wal_build_tuple(bktype_stats, backend_stats->stat_reset_timestamp));
+	if (!wal_stats)
+		PG_RETURN_NULL();
+
+	return (pg_stat_wal_build_tuple(wal_stats->wal_counters,
+									wal_stats->stat_reset_timestamp));
 }
 
 /*
@@ -2175,6 +2189,7 @@ pg_stat_reset_backend_stats(PG_FUNCTION_ARGS)
 	PGPROC	   *proc;
 	PgBackendStatus *beentry;
 	ProcNumber	procNumber;
+	TimestampTz ts;
 	int			backend_pid = PG_GETARG_INT32(0);
 
 	proc = BackendPidGetProc(backend_pid);
@@ -2196,6 +2211,14 @@ pg_stat_reset_backend_stats(PG_FUNCTION_ARGS)
 	if (!pgstat_tracks_backend_bktype(beentry->st_backendType))
 		PG_RETURN_VOID();
 
+	/*
+	 * Accumulate the backend's WAL stats into the global stats, then zero the
+	 * entry.
+	 */
+	ts = GetCurrentTimestamp();
+	pgstat_wal_reset_backend_cb(procNumber, ts);
+
+	/* Reset IO and Lock stats still in PGSTAT_KIND_BACKEND */
 	pgstat_reset(PGSTAT_KIND_BACKEND, InvalidOid, procNumber);
 
 	PG_RETURN_VOID();
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 187d82c96fe..9a71b8d3cd8 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -593,7 +593,6 @@ typedef struct PgStat_Backend
 {
 	TimestampTz stat_reset_timestamp;
 	PgStat_BktypeIO io_stats;
-	PgStat_WalCounters wal_counters;
 	PgStat_PendingLock lock_stats;
 } PgStat_Backend;
 
@@ -946,6 +945,8 @@ extern void pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_
 
 extern void pgstat_report_wal(bool force);
 extern PgStat_WalStats *pgstat_fetch_stat_wal(void);
+extern PgStat_WalStats *pgstat_fetch_stat_backend_wal(ProcNumber procnum);
+extern void pgstat_wal_reset_backend_cb(ProcNumber procnum, TimestampTz ts);
 
 
 /*
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index da5a67cf827..d0c9379b42b 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -532,9 +532,22 @@ typedef struct PgStatShared_PerBackendEntry
 	BackendType backend_type;
 } PgStatShared_PerBackendEntry;
 
+/*
+ * Per-backend entry for WAL statistics, stored in an array indexed by
+ * ProcNumber.
+ */
+typedef struct PgStatShared_WalBackendEntry
+{
+	PgStatShared_PerBackendEntry header;
+	PgStat_WalStats stats;
+} PgStatShared_WalBackendEntry;
+
 typedef struct PgStatShared_Wal
 {
-	/* lock protects ->stats */
+	/*
+	 * The lock protects global stats and serializes snapshots and resets with
+	 * transfers from per-backend entries.
+	 */
 	LWLock		lock;
 	PgStat_WalStats stats;
 } PgStatShared_Wal;
@@ -798,9 +811,8 @@ extern void pgstat_archiver_snapshot_cb(void);
 
 /* flags for pgstat_flush_backend() */
 #define PGSTAT_BACKEND_FLUSH_IO		(1 << 0)	/* Flush I/O statistics */
-#define PGSTAT_BACKEND_FLUSH_WAL   (1 << 1) /* Flush WAL statistics */
 #define PGSTAT_BACKEND_FLUSH_LOCK  (1 << 2) /* Flush lock statistics */
-#define PGSTAT_BACKEND_FLUSH_ALL   (PGSTAT_BACKEND_FLUSH_IO | PGSTAT_BACKEND_FLUSH_WAL | PGSTAT_BACKEND_FLUSH_LOCK)
+#define PGSTAT_BACKEND_FLUSH_ALL   (PGSTAT_BACKEND_FLUSH_IO | PGSTAT_BACKEND_FLUSH_LOCK)
 
 extern bool pgstat_flush_backend(bool nowait, uint32 flags);
 extern bool pgstat_backend_flush_cb(bool nowait);
@@ -950,6 +962,9 @@ extern bool pgstat_wal_flush_cb(bool nowait);
 extern void pgstat_wal_init_shmem_cb(void *stats);
 extern void pgstat_wal_reset_all_cb(TimestampTz ts);
 extern void pgstat_wal_snapshot_cb(void);
+extern void pgstat_wal_acc_backend_cb(void);
+extern void pgstat_wal_acc_all_backends(void);
+extern void pgstat_wal_per_backend_acc_cb(void *dst, void *entry);
 
 
 /*
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 1306c96c3e7..95b87d32a62 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2308,6 +2308,7 @@ PgStatShared_ReplSlot
 PgStatShared_SLRU
 PgStatShared_Subscription
 PgStatShared_Wal
+PgStatShared_WalBackendEntry
 PgStat_ArchiverStats
 PgStat_Backend
 PgStat_BackendPending
-- 
2.34.1

