From 82f7aeac8adc77de14b6c6fb0fb76cd4b6adb16e Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Fri, 28 Aug 2026 13:28:10 +0200
Subject: [PATCH v1] Revert online data checksums transitions

The feature to enable, or disable, data checksums in an online
cluster saw a number of postcommit fixes during the beta period.
Suspicions were raised about the risk of more issues surfacing
after GA.  To avoid shipping code which may have bugs, this
reverts in full, or in part, the following commits:

aaf8b9989f7, cd857dec0e0, 5fee7cab1b8, 25b922ec582, 8fb8ded8895,
b3a37ffbc5b, abac86c7a27, 3a18526e8d6, 01805b7d16b, 343d98c3601,
e469e4784ea, 8d22f523245, e5e1f6dc795, 5ab239c9a90, 0ca1b301059,
9a39056c418, 2018bd61679, 1df361e3d82, bf25e5571b3, 381d19da153,
b120358c612, 07009121c23, d771b0a907e, f19c0eccae9, 0907112d388,
397f0fd06ed, 602f19c84ca, e3a27cad462, 4ae3e98c02c, b364828f825

A few bits remain as they have merit on their own:
* The fix for offline checksums not preserving initial state in
  pg_control_init.  The test case for this fix has been moved to
  src/bin/pg_checksums/t/002_actions.pl to survive the revert
  which removed the previous location.
* When a page verification is logged, the additional note which
  informs if the buffer will be zeroed out was kept to aid any
  debugging around checksum failures.
* The Data Checksum section in the docs was kept, but rewritten
  to reflect the current state.
* The enum containing checksum states is kept and some hardcoded
  references to the off state (0) are replaced with the label
  PG_DATA_CHECKSUM_OFF instead.

Discussion: https://postgr.es/m/anwm6UPxoVS41QA2@bdtpg
Discussion: https://postgr.es/m/CA+Tgmob9NY6m0YNFTQ4nFH2d0iC9SQRruDYxfndGKKzh8OC80w@mail.gmail.com
Discussion: https://postgr.es/m/E07A611B-9CF3-4FDB-8CE8-A221E39040EC%40yesql.se
---
 doc/src/sgml/config.sgml                      |    5 +-
 doc/src/sgml/func/func-admin.sgml             |   79 -
 doc/src/sgml/func/func-info.sgml              |    5 -
 doc/src/sgml/glossary.sgml                    |   20 +-
 doc/src/sgml/images/Makefile                  |    1 -
 doc/src/sgml/images/datachecksums.gv          |   14 -
 doc/src/sgml/images/datachecksums.svg         |   81 -
 doc/src/sgml/monitoring.sgml                  |  228 +-
 doc/src/sgml/ref/pg_basebackup.sgml           |    6 -
 doc/src/sgml/ref/pg_checksums.sgml            |   12 +-
 doc/src/sgml/regress.sgml                     |   14 -
 doc/src/sgml/release-19.sgml                  |   26 -
 doc/src/sgml/wal.sgml                         |  185 +-
 src/backend/access/rmgrdesc/xlogdesc.c        |   58 +-
 src/backend/access/transam/xlog.c             |  553 +----
 src/backend/backup/basebackup.c               |   90 +-
 src/backend/catalog/system_views.sql          |   19 -
 src/backend/commands/dbcommands.c             |   34 -
 src/backend/postmaster/Makefile               |    1 -
 src/backend/postmaster/auxprocess.c           |   28 -
 src/backend/postmaster/bgworker.c             |    9 -
 src/backend/postmaster/datachecksum_state.c   | 1979 -----------------
 src/backend/postmaster/meson.build            |    1 -
 src/backend/postmaster/postmaster.c           |    5 -
 src/backend/replication/logical/decode.c      |   16 -
 src/backend/storage/ipc/procsignal.c          |    8 -
 src/backend/storage/page/README               |    4 +-
 src/backend/storage/page/bufpage.c            |   18 +-
 src/backend/utils/activity/pgstat_backend.c   |    2 -
 src/backend/utils/activity/pgstat_io.c        |   35 -
 .../utils/activity/wait_event_names.txt       |    3 -
 src/backend/utils/adt/pgstatfuncs.c           |    8 +-
 src/backend/utils/init/miscinit.c             |    3 +-
 src/backend/utils/init/postinit.c             |   30 +-
 src/backend/utils/misc/guc_parameters.dat     |    6 +-
 src/backend/utils/misc/guc_tables.c           |    9 +-
 src/backend/utils/misc/pg_controldata.c       |    9 +-
 src/backend/utils/misc/postgresql.conf.sample |   10 +-
 src/bin/pg_checksums/t/002_actions.pl         |    5 +
 src/bin/pg_controldata/pg_controldata.c       |    2 -
 src/bin/pg_upgrade/controldata.c              |    9 -
 src/bin/pg_waldump/t/001_basic.pl             |    3 +-
 src/include/access/rmgrlist.h                 |    1 -
 src/include/access/xlog.h                     |   20 +-
 src/include/access/xlog_internal.h            |    6 -
 src/include/catalog/pg_control.h              |    7 -
 src/include/catalog/pg_proc.dat               |   12 -
 src/include/commands/progress.h               |   16 -
 src/include/miscadmin.h                       |   10 -
 src/include/postmaster/datachecksum_state.h   |   28 -
 src/include/postmaster/proctypelist.h         |    2 -
 src/include/replication/decode.h              |    1 -
 src/include/storage/checksum.h                |   13 +-
 src/include/storage/lwlocklist.h              |    1 -
 src/include/storage/procsignal.h              |    4 -
 src/include/storage/subsystemlist.h           |    1 -
 src/include/utils/backend_progress.h          |    1 -
 src/test/modules/Makefile                     |    1 -
 src/test/modules/meson.build                  |    1 -
 src/test/modules/test_checksums/.gitignore    |    2 -
 src/test/modules/test_checksums/Makefile      |   36 -
 src/test/modules/test_checksums/README        |   30 -
 src/test/modules/test_checksums/meson.build   |   40 -
 .../modules/test_checksums/t/001_basic.pl     |  221 --
 .../modules/test_checksums/t/002_restarts.pl  |  160 --
 .../test_checksums/t/003_standby_restarts.pl  |  288 ---
 .../modules/test_checksums/t/004_offline.pl   |  108 -
 .../modules/test_checksums/t/005_injection.pl |  215 --
 .../test_checksums/t/006_pgbench_single.pl    |  285 ---
 .../test_checksums/t/007_pgbench_standby.pl   |  411 ----
 src/test/modules/test_checksums/t/008_pitr.pl |  192 --
 src/test/modules/test_checksums/t/009_fpi.pl  |   64 -
 .../test_checksums/t/010_backup_straddle.pl   |  260 ---
 .../test_checksums/t/011_standby_straddle.pl  |  249 ---
 .../test_checksums/t/DataChecksums/Utils.pm   |  243 --
 .../test_checksums/test_checksums--1.0.sql    |   16 -
 .../modules/test_checksums/test_checksums.c   |  105 -
 .../test_checksums/test_checksums.control     |    4 -
 src/test/regress/expected/rules.out           |   38 -
 src/test/regress/expected/stats.out           |   11 +-
 src/tools/pgindent/typedefs.list              |    6 -
 81 files changed, 79 insertions(+), 6663 deletions(-)
 delete mode 100644 doc/src/sgml/images/datachecksums.gv
 delete mode 100644 doc/src/sgml/images/datachecksums.svg
 delete mode 100644 src/backend/postmaster/datachecksum_state.c
 delete mode 100644 src/include/postmaster/datachecksum_state.h
 delete mode 100644 src/test/modules/test_checksums/.gitignore
 delete mode 100644 src/test/modules/test_checksums/Makefile
 delete mode 100644 src/test/modules/test_checksums/README
 delete mode 100644 src/test/modules/test_checksums/meson.build
 delete mode 100644 src/test/modules/test_checksums/t/001_basic.pl
 delete mode 100644 src/test/modules/test_checksums/t/002_restarts.pl
 delete mode 100644 src/test/modules/test_checksums/t/003_standby_restarts.pl
 delete mode 100644 src/test/modules/test_checksums/t/004_offline.pl
 delete mode 100644 src/test/modules/test_checksums/t/005_injection.pl
 delete mode 100644 src/test/modules/test_checksums/t/006_pgbench_single.pl
 delete mode 100644 src/test/modules/test_checksums/t/007_pgbench_standby.pl
 delete mode 100644 src/test/modules/test_checksums/t/008_pitr.pl
 delete mode 100644 src/test/modules/test_checksums/t/009_fpi.pl
 delete mode 100644 src/test/modules/test_checksums/t/010_backup_straddle.pl
 delete mode 100644 src/test/modules/test_checksums/t/011_standby_straddle.pl
 delete mode 100644 src/test/modules/test_checksums/t/DataChecksums/Utils.pm
 delete mode 100644 src/test/modules/test_checksums/test_checksums--1.0.sql
 delete mode 100644 src/test/modules/test_checksums/test_checksums.c
 delete mode 100644 src/test/modules/test_checksums/test_checksums.control

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 97aeadfc35f..afb8651f07b 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -7498,7 +7498,6 @@ local0.*    /var/log/postgresql
          <member><literal>bgworker</literal></member>
          <member><literal>bgwriter</literal></member>
          <member><literal>checkpointer</literal></member>
-         <member><literal>checksums</literal></member>
          <member><literal>ioworker</literal></member>
          <member><literal>postmaster</literal></member>
          <member><literal>slotsyncworker</literal></member>
@@ -12305,7 +12304,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
      </varlistentry>
 
      <varlistentry id="guc-data-checksums" xreflabel="data_checksums">
-      <term><varname>data_checksums</varname> (<type>enum</type>)
+      <term><varname>data_checksums</varname> (<type>bool</type>)
       <indexterm>
        <primary><varname>data_checksums</varname> configuration parameter</primary>
       </indexterm>
@@ -12313,8 +12312,6 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
       <listitem>
        <para>
         Reports the state of data checksums for this cluster.
-        Possible values are <literal>on</literal>, <literal>off</literal>,
-        <literal>inprogress-on</literal> and <literal>inprogress-off</literal>.
         See <xref linkend="checksums"/> for more information.
        </para>
       </listitem>
diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml
index 0eae1c1f616..ff860363f3f 100644
--- a/doc/src/sgml/func/func-admin.sgml
+++ b/doc/src/sgml/func/func-admin.sgml
@@ -3122,83 +3122,4 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
    </table>
 
   </sect2>
-
-  <sect2 id="functions-admin-checksum">
-   <title>Data Checksum Functions</title>
-
-   <para>
-    The functions shown in <xref linkend="functions-checksums-table" /> can
-    be used to enable or disable data checksums in a running cluster.
-   </para>
-   <para>
-    Changing data checksums can be done in a cluster with concurrent activity
-    without blocking queries, but overall system performance will be affected.
-    See <xref linkend="checksums" /> for further details on how changing the
-    data checksums state can affect a system and possible mitigations for how
-    to reduce the impact.
-   </para>
-
-   <table id="functions-checksums-table">
-    <title>Data Checksum Functions</title>
-    <tgroup cols="1">
-     <thead>
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        Function
-       </para>
-       <para>
-        Description
-       </para></entry>
-      </row>
-     </thead>
-
-     <tbody>
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>pg_enable_data_checksums</primary>
-        </indexterm>
-        <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type>, <parameter>cost_limit</parameter> <type>int</type></optional> )
-        <returnvalue>void</returnvalue>
-       </para>
-       <para>
-        Initiates the process of enabling data checksums for the cluster. This
-        will set the data checksums state to <literal>inprogress-on</literal>
-        as well as start a background worker that will process all pages in all
-        databases and enable data checksums on them.  When all pages have
-        been processed, the cluster will automatically set data checksums state
-        to <literal>on</literal>.  This operation is WAL logged and replicated
-        to all standby nodes.
-       </para>
-       <para>
-        If <parameter>cost_delay</parameter> and <parameter>cost_limit</parameter> are
-        specified, the process is throttled using the same principles as
-        <link linkend="runtime-config-resource-vacuum-cost">Cost-based Vacuum Delay</link>.
-       </para>
-       </entry>
-      </row>
-
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>pg_disable_data_checksums</primary>
-        </indexterm>
-        <function>pg_disable_data_checksums</function> ()
-        <returnvalue>void</returnvalue>
-       </para>
-       <para>
-        Disables data checksum calculation and validation for the cluster. This
-        will set the data checksum state to <literal>inprogress-off</literal>
-        while data checksums are being disabled.  When all active backends have
-        stopped validating data checksums, the data checksum state will be
-        set to <literal>off</literal>.
-       </para>
-       </entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
-
-  </sect2>
-
   </sect1>
diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml
index 2f03766b67a..713c837fc02 100644
--- a/doc/src/sgml/func/func-info.sgml
+++ b/doc/src/sgml/func/func-info.sgml
@@ -3496,11 +3496,6 @@ acl      | {postgres=arwdDxtm/postgres,foo=r/postgres}
        <entry><type>xid</type></entry>
       </row>
 
-      <row>
-       <entry><structfield>data_page_checksum_version</structfield></entry>
-       <entry><type>integer</type></entry>
-      </row>
-
       <row>
        <entry><structfield>checkpoint_time</structfield></entry>
        <entry><type>timestamp with time zone</type></entry>
diff --git a/doc/src/sgml/glossary.sgml b/doc/src/sgml/glossary.sgml
index b9a3cb83bc2..899fa4299e2 100644
--- a/doc/src/sgml/glossary.sgml
+++ b/doc/src/sgml/glossary.sgml
@@ -234,9 +234,8 @@
      which runs system- or user-supplied code.
      Serves as infrastructure for several features in
      <productname>PostgreSQL</productname>, such as
-     <glossterm linkend="glossary-replication">logical replication</glossterm>,
-     <glossterm linkend="glossary-parallel-query">parallel queries</glossterm> and
-     <glossterm linkend="glossary-data-checksums-process">data checksums processing</glossterm>.
+     <glossterm linkend="glossary-replication">logical replication</glossterm> and
+     <glossterm linkend="glossary-parallel-query">parallel queries</glossterm>.
      In addition, <glossterm linkend="glossary-extension">Extensions</glossterm> can add
      custom background worker processes.
    </para>
@@ -575,21 +574,6 @@
    <glosssee otherterm="glossary-data-directory" />
   </glossentry>
 
-  <glossentry id="glossary-data-checksums-process">
-   <glossterm>Data Checksums (process)</glossterm>
-   <glossdef>
-    <para>
-     A set of
-     <glossterm linkend="glossary-background-worker">background worker</glossterm>
-     processes which can enable or disable data checksums in a running cluster.
-     The process which coordinates the work is known as the
-     <firstterm>data checksums launcher</firstterm> and the process which
-     operates on the individual databases is known as the
-     <firstterm>data checksums worker</firstterm>.
-    </para>
-   </glossdef>
-  </glossentry>
-
   <glossentry id="glossary-database">
    <glossterm>Database</glossterm>
    <glossdef>
diff --git a/doc/src/sgml/images/Makefile b/doc/src/sgml/images/Makefile
index 9362c30998e..157c1ff366a 100644
--- a/doc/src/sgml/images/Makefile
+++ b/doc/src/sgml/images/Makefile
@@ -3,7 +3,6 @@
 # see README in this directory about image handling
 
 ALL_IMAGES = \
-	datachecksums.svg \
 	genetic-algorithm.svg \
 	gin.svg \
 	pagelayout.svg \
diff --git a/doc/src/sgml/images/datachecksums.gv b/doc/src/sgml/images/datachecksums.gv
deleted file mode 100644
index dff3ff7340a..00000000000
--- a/doc/src/sgml/images/datachecksums.gv
+++ /dev/null
@@ -1,14 +0,0 @@
-digraph G {
-    A -> B [label="SELECT pg_enable_data_checksums()"];
-    B -> C;
-    D -> A;
-    C -> D [label="SELECT pg_disable_data_checksums()"];
-    E -> A [label=" --no-data-checksums"];
-    E -> C [label=" --data-checksums"];
-
-    A [label="off"];
-    B [label="inprogress-on"];
-    C [label="on"];
-    D [label="inprogress-off"];
-    E [label="initdb"];
-}
diff --git a/doc/src/sgml/images/datachecksums.svg b/doc/src/sgml/images/datachecksums.svg
deleted file mode 100644
index 8c58f42922e..00000000000
--- a/doc/src/sgml/images/datachecksums.svg
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Generated by graphviz version 14.0.5 (20251129.0259)
- -->
-<!-- Title: G Pages: 1 -->
-<svg width="409pt" height="383pt"
- viewBox="0.00 0.00 409.00 383.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 378.5)">
-<title>G</title>
-<polygon fill="white" stroke="none" points="-4,4 -4,-378.5 404.74,-378.5 404.74,4 -4,4"/>
-<!-- A -->
-<g id="node1" class="node">
-<title>A</title>
-<ellipse fill="none" stroke="black" cx="80.12" cy="-268" rx="27" ry="18"/>
-<text xml:space="preserve" text-anchor="middle" x="80.12" y="-262.95" font-family="Times,serif" font-size="14.00">off</text>
-</g>
-<!-- B -->
-<g id="node2" class="node">
-<title>B</title>
-<ellipse fill="none" stroke="black" cx="137.12" cy="-179.5" rx="61.59" ry="18"/>
-<text xml:space="preserve" text-anchor="middle" x="137.12" y="-174.45" font-family="Times,serif" font-size="14.00">inprogress&#45;on</text>
-</g>
-<!-- A&#45;&gt;B -->
-<g id="edge1" class="edge">
-<title>A&#45;&gt;B</title>
-<path fill="none" stroke="black" d="M76.5,-249.68C75.22,-239.14 75.3,-225.77 81.12,-215.5 84.2,-210.08 88.49,-205.38 93.35,-201.34"/>
-<polygon fill="black" stroke="black" points="95.22,-204.31 101.33,-195.66 91.16,-198.61 95.22,-204.31"/>
-<text xml:space="preserve" text-anchor="middle" x="187.62" y="-218.7" font-family="Times,serif" font-size="14.00">SELECT pg_enable_data_checksums()</text>
-</g>
-<!-- C -->
-<g id="node3" class="node">
-<title>C</title>
-<ellipse fill="none" stroke="black" cx="137.12" cy="-106.5" rx="27" ry="18"/>
-<text xml:space="preserve" text-anchor="middle" x="137.12" y="-101.45" font-family="Times,serif" font-size="14.00">on</text>
-</g>
-<!-- B&#45;&gt;C -->
-<g id="edge2" class="edge">
-<title>B&#45;&gt;C</title>
-<path fill="none" stroke="black" d="M137.12,-161.31C137.12,-153.73 137.12,-144.6 137.12,-136.04"/>
-<polygon fill="black" stroke="black" points="140.62,-136.04 137.12,-126.04 133.62,-136.04 140.62,-136.04"/>
-</g>
-<!-- D -->
-<g id="node4" class="node">
-<title>D</title>
-<ellipse fill="none" stroke="black" cx="63.12" cy="-18" rx="63.12" ry="18"/>
-<text xml:space="preserve" text-anchor="middle" x="63.12" y="-12.95" font-family="Times,serif" font-size="14.00">inprogress&#45;off</text>
-</g>
-<!-- C&#45;&gt;D -->
-<g id="edge4" class="edge">
-<title>C&#45;&gt;D</title>
-<path fill="none" stroke="black" d="M124.23,-90.43C113.36,-77.73 97.58,-59.28 84.77,-44.31"/>
-<polygon fill="black" stroke="black" points="87.78,-42.44 78.62,-37.12 82.46,-46.99 87.78,-42.44"/>
-<text xml:space="preserve" text-anchor="middle" x="214.75" y="-57.2" font-family="Times,serif" font-size="14.00">SELECT pg_disable_data_checksums()</text>
-</g>
-<!-- D&#45;&gt;A -->
-<g id="edge3" class="edge">
-<title>D&#45;&gt;A</title>
-<path fill="none" stroke="black" d="M62.52,-36.28C61.62,-68.21 60.54,-138.57 66.12,-197.5 67.43,-211.24 70.27,-226.28 73.06,-238.85"/>
-<polygon fill="black" stroke="black" points="69.64,-239.59 75.32,-248.54 76.46,-238 69.64,-239.59"/>
-</g>
-<!-- E -->
-<g id="node5" class="node">
-<title>E</title>
-<ellipse fill="none" stroke="black" cx="198.12" cy="-356.5" rx="32.41" ry="18"/>
-<text xml:space="preserve" text-anchor="middle" x="198.12" y="-351.45" font-family="Times,serif" font-size="14.00">initdb</text>
-</g>
-<!-- E&#45;&gt;A -->
-<g id="edge5" class="edge">
-<title>E&#45;&gt;A</title>
-<path fill="none" stroke="black" d="M179.16,-341.6C159.64,-327.29 129.05,-304.86 107.03,-288.72"/>
-<polygon fill="black" stroke="black" points="109.23,-286 99.1,-282.91 105.09,-291.64 109.23,-286"/>
-<text xml:space="preserve" text-anchor="middle" x="208.57" y="-307.2" font-family="Times,serif" font-size="14.00"> &#45;&#45;no&#45;data&#45;checksums</text>
-</g>
-<!-- E&#45;&gt;C -->
-<g id="edge6" class="edge">
-<title>E&#45;&gt;C</title>
-<path fill="none" stroke="black" d="M227.13,-348.04C242.29,-342.72 259.95,-334.06 271.12,-320.5 301.5,-283.62 316.36,-257.78 294.12,-215.5 268.41,-166.6 209.42,-135.53 171.52,-119.85"/>
-<polygon fill="black" stroke="black" points="172.96,-116.65 162.37,-116.21 170.37,-123.16 172.96,-116.65"/>
-<text xml:space="preserve" text-anchor="middle" x="350.87" y="-218.7" font-family="Times,serif" font-size="14.00"> &#45;&#45;data&#45;checksums</text>
-</g>
-</g>
-</svg>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 66f6127a410..ef13f07e7eb 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -436,15 +436,6 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
       </entry>
      </row>
 
-     <row>
-      <entry><structname>pg_stat_progress_data_checksums</structname><indexterm><primary>pg_stat_progress_data_checksums</primary></indexterm></entry>
-      <entry>One row for the data checksum launcher process while data
-       checksums are being enabled or disabled.  When enabling data
-       checksums, the view also has one row for each worker process,
-       showing current progress.
-       See <xref linkend="data-checksum-progress-reporting"/>.
-      </entry>
-     </row>
     </tbody>
    </tgroup>
   </table>
@@ -6140,10 +6131,10 @@ FROM pg_stat_get_backend_idset() AS backendid;
    which support progress reporting are <command>ANALYZE</command>,
    <command>COPY</command>, <command>CREATE INDEX</command>,
    <command>REPACK</command> (and its obsolete spelling <command>CLUSTER</command>),
-   <command>VACUUM</command>,
+   <command>VACUUM</command> and
    <xref linkend="protocol-replication-base-backup"/> (i.e., replication
    command that <xref linkend="app-pgbasebackup"/> issues to take
-   a base backup), and online data checksum operations.
+   a base backup).
    This may be expanded in the future.
   </para>
 
@@ -7870,221 +7861,6 @@ FROM pg_stat_get_backend_idset() AS backendid;
   </table>
 
  </sect2>
-
- <sect2 id="data-checksum-progress-reporting">
-  <title>Data Checksum Progress Reporting</title>
-
-  <indexterm>
-   <primary>pg_stat_progress_data_checksums</primary>
-  </indexterm>
-
-  <para>
-   When data checksums are being enabled or disabled on a running cluster, the
-   <structname>pg_stat_progress_data_checksums</structname> view will contain
-   a row for the launcher process.  When enabling data checksums, the view
-   will also contain one row for each worker process which is currently
-   calculating and writing checksums for the data pages in a database.  The
-   launcher provides an overview of the overall progress, such as how many
-   databases have been processed and how many remain, while the workers track
-   progress for currently processed databases.
-  </para>
-
-  <table id="pg-stat-progress-data-checksums-view" xreflabel="pg_stat_progress_data_checksums">
-   <title><structname>pg_stat_progress_data_checksums</structname> View</title>
-   <tgroup cols="1">
-    <thead>
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        Column Type
-       </para>
-       <para>
-        Description
-       </para>
-      </entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>pid</structfield> <type>integer</type>
-       </para>
-       <para>
-        Process ID of the data checksum process, launcher or worker.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>datid</structfield> <type>oid</type>
-       </para>
-       <para>
-        OID of this database, or <literal>0</literal> for the launcher process.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>datname</structfield> <type>name</type>
-       </para>
-       <para>
-        Name of this database, or <literal>NULL</literal> for the
-        launcher process.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>phase</structfield> <type>text</type>
-       </para>
-       <para>
-        Current processing phase, see <xref linkend="datachecksum-phases"/>
-        for description of the phases.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>databases_total</structfield> <type>bigint</type>
-       </para>
-       <para>
-        The total number of databases which will be processed. Only the
-        launcher process has this value set when enabling data checksums;
-        otherwise this is set to <literal>NULL</literal>.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>databases_done</structfield> <type>bigint</type>
-       </para>
-       <para>
-        The number of databases which have been processed. Only the launcher
-        process has this value set when enabling data checksums; otherwise
-        this is set to <literal>NULL</literal>.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>relations_total</structfield> <type>bigint</type>
-       </para>
-       <para>
-        The total number of relations which will be processed, or
-        <literal>NULL</literal> if the worker process hasn't
-        calculated the number of relations yet. The launcher process has
-        this set to <literal>NULL</literal> since it isn't responsible for
-        processing relations, only launching worker processes.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>relations_done</structfield> <type>bigint</type>
-       </para>
-       <para>
-        The number of relations which have been processed. The launcher
-        process has this set to <literal>NULL</literal>.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>blocks_total</structfield> <type>bigint</type>
-       </para>
-       <para>
-        The number of blocks in the current relation which will be processed,
-        or <literal>NULL</literal> if the worker process hasn't
-        calculated the number of blocks yet. The launcher process has
-        this set to <literal>NULL</literal>.
-       </para>
-      </entry>
-     </row>
-
-     <row>
-      <entry role="catalog_table_entry">
-       <para role="column_definition">
-        <structfield>blocks_done</structfield> <type>bigint</type>
-       </para>
-       <para>
-        The number of blocks in the current relation which have been processed.
-        The launcher process has this set to <literal>NULL</literal>.
-       </para>
-      </entry>
-     </row>
-
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="datachecksum-phases">
-   <title>Data Checksum Phases</title>
-   <tgroup cols="2">
-    <colspec colname="col1" colwidth="1*"/>
-    <colspec colname="col2" colwidth="2*"/>
-    <thead>
-     <row>
-      <entry>Phase</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-    <tbody>
-     <row>
-      <entry><literal>enabling</literal></entry>
-      <entry>
-       The command is currently enabling data checksums on the cluster.
-      </entry>
-     </row>
-     <row>
-      <entry><literal>disabling</literal></entry>
-      <entry>
-       The command is currently disabling data checksums on the cluster.
-      </entry>
-     </row>
-     <row>
-      <entry><literal>done</literal></entry>
-      <entry>
-       The command is done and the data checksum state in the cluster has
-       changed.
-      </entry>
-     </row>
-     <row>
-      <entry><literal>waiting on barrier</literal></entry>
-      <entry>
-       The command is currently waiting for the current active backends to
-       acknowledge the change in data checksum state.
-      </entry>
-     </row>
-     <row>
-      <entry><literal>waiting on temporary tables</literal></entry>
-      <entry>
-       The command is currently waiting for all temporary tables which existed
-       at the time the command was started to be removed.
-      </entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
- </sect2>
-
  </sect1>
 
  <sect1 id="dynamic-trace">
diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml
index 3117968d125..fecee08b0a5 100644
--- a/doc/src/sgml/ref/pg_basebackup.sgml
+++ b/doc/src/sgml/ref/pg_basebackup.sgml
@@ -788,12 +788,6 @@ PostgreSQL documentation
         in the <link linkend="monitoring-pg-stat-database-view">
         <structname>pg_stat_database</structname></link> view.
        </para>
-       <para>
-        Checksums must be enabled on the server for the duration of the base
-        backup in order to be verified.  If checksums are in the process of
-        being enabled when the base backup starts then checksum verification is
-        disabled for the base backup.
-       </para>
       </listitem>
      </varlistentry>
     </variablelist>
diff --git a/doc/src/sgml/ref/pg_checksums.sgml b/doc/src/sgml/ref/pg_checksums.sgml
index ae66fad3f0f..fcded6b4a05 100644
--- a/doc/src/sgml/ref/pg_checksums.sgml
+++ b/doc/src/sgml/ref/pg_checksums.sgml
@@ -39,23 +39,13 @@ PostgreSQL documentation
    <application>pg_checksums</application> checks, enables or disables data
    checksums in a <productname>PostgreSQL</productname> cluster.  The server
    must be shut down cleanly before running <application>pg_checksums</application>.
-   Checksums can also be enabled while the cluster is running using
-   <xref linkend="checksums-online-enable-disable"/> processing, see
-   <xref linkend="checksums"/> for further details on the different approaches.
+   See <xref linkend="checksums"/> for further details on data checksums.
    When verifying checksums, the exit
    status is zero if there are no checksum errors, and nonzero if at least one
    checksum failure is detected. When enabling or disabling checksums, the
    exit status is nonzero if the operation failed.
   </para>
 
-  <para>
-   When enabling checksums with <application>pg_checksums</application>, if
-   checksums were in the process of being enabled using
-   <xref linkend="checksums-online-enable-disable"/>  when the cluster was shut
-   down, <application>pg_checksums</application> will still process all
-   relation files regardless of the progress of online checksum processing.
-  </para>
-
   <para>
    When verifying checksums, every file in the cluster is scanned. When
    enabling checksums, each relation file block with a changed checksum is
diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml
index c74941bfbf2..873387ec168 100644
--- a/doc/src/sgml/regress.sgml
+++ b/doc/src/sgml/regress.sgml
@@ -275,20 +275,6 @@ make check-world PG_TEST_EXTRA='kerberos ldap ssl load_balance libpq_encryption'
 </programlisting>
    The following values are currently supported:
    <variablelist>
-    <varlistentry>
-     <term><literal>checksum</literal>, <literal>checksum_extended</literal></term>
-     <listitem>
-      <para>
-       Runs additional tests for enabling data checksums which inject faults
-       to cause re-tries in the processing, as well as tests that run pgbench
-       concurrently and randomly restarts the cluster.  Some of these test
-       suites require injection points enabled in the installation.
-       <literal>checksum_extended</literal> is an extended version with
-       longer runtime, injected random delays and larger datasets.
-      </para>
-     </listitem>
-    </varlistentry>
-
     <varlistentry>
      <term><literal>kerberos</literal></term>
      <listitem>
diff --git a/doc/src/sgml/release-19.sgml b/doc/src/sgml/release-19.sgml
index a8046ab41f0..bb8faed8c18 100644
--- a/doc/src/sgml/release-19.sgml
+++ b/doc/src/sgml/release-19.sgml
@@ -55,13 +55,6 @@
      </para>
     </listitem>
 
-    <listitem>
-     <para>
-      Data checksums can now be
-      <link linkend="checksums-online-enable-disable">enabled or disabled while the database server is running</link>.
-     </para>
-    </listitem>
-
     <listitem>
      <para>
       A new <link linkend="sql-wait-for"><command>WAIT FOR</command></link>
@@ -1391,25 +1384,6 @@ The previous warning was 40 million.  Warnings are issued to clients and in the
      <title>Server Configuration</title>
 
      <itemizedlist>
-<!--
-Author: Daniel Gustafsson <dgustafsson@postgresql.org>
-2026-04-03 [f19c0ecca] Online enabling and disabling of data checksums
-Author: Daniel Gustafsson <dgustafsson@postgresql.org>
-2026-04-08 [b364828f8] doc: Fix data_checksums data type
--->
-
-<listitem>
-<para>
-Allow <link linkend="functions-admin-checksum">online enabling</link> and disabling of <link linkend="checksums">data checksums</link> (Daniel Gustafsson, Magnus Hagander, Tomas Vondra)
-<ulink url="&commit_baseurl;f19c0ecca">&sect;</ulink>
-<ulink url="&commit_baseurl;b364828f8">&sect;</ulink>
-</para>
-
-<para>
-Previously the checksum status could only be changed while the cluster was offline using <link linkend="app-pgchecksums"><application>pg_checksums</application></link>.
-</para>
-</listitem>
-
 <!--
 Author: Nathan Bossart <nathan@postgresql.org>
 2026-03-27 [d7965d65f] Add rudimentary table prioritization to autovacuum.
diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml
index ec62d17fbcc..79ac6c247f8 100644
--- a/doc/src/sgml/wal.sgml
+++ b/doc/src/sgml/wal.sgml
@@ -236,20 +236,20 @@
   </indexterm>
 
   <para>
-   By default, data pages are protected by checksums, but this can
-   optionally be disabled for a cluster. When enabled, each data page includes
-   a checksum that is updated when the page is written and verified each time
-   the page is read. Only data pages are protected by checksums; internal data
-   structures and temporary files are not.
+   By default, data pages are protected by checksums, but this can optionally
+   be disabled for a cluster. When enabled, each data page includes a checksum
+   that is updated when the page is written and verified each time the page is
+   read. Only data pages are protected by checksums; internal data structures
+   and temporary files are not.
   </para>
 
   <para>
    Checksums can be disabled when the cluster is initialized using <link
    linkend="app-initdb-data-checksums"><application>initdb</application></link>.
-   They can also be enabled or disabled at a later time either as an offline
-   operation or online in a running cluster allowing concurrent access. Data
-   checksums are enabled or disabled at the full cluster level, and cannot be
-   specified individually for databases, tables or replicated cluster members.
+   They can also be enabled or disabled at a later time as an offline
+   operation.  Data checksums are enabled or disabled at the full cluster
+   level, and cannot be specified individually for databases, tables or
+   replicated cluster members.
   </para>
 
   <para>
@@ -257,51 +257,11 @@
    value of the read-only configuration variable <xref
    linkend="guc-data-checksums" /> by issuing the command <command>SHOW
    data_checksums</command>.  <link linkend="functions-pg-control-init">
-   <literal>pg_control_init</literal></link> and
-   <link linkend="functions-pg-control-checkpoint">
-   <literal>pg_control_checkpoint</literal></link> can also be used for
-   inspecting the data checksum state at cluster initialization and current
-   checkpoint.  Data checksum states are often referred to as data checksum
-   versions using an integer representation due to how they were originally
-   implemented.  <xref linkend="data-checksums-mapping" /> contains a mapping
-   between state names and versions, which are defined in
-   <filename>src/include/storage/checksum.h</filename>.
+   <literal>pg_control_init</literal></link>
+    can also be used for
+   inspecting the data checksum state at cluster initialization.
   </para>
 
-  <table id="data-checksums-mapping">
-   <title>Data Checksums States and Version Mapping</title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry>State</entry>
-      <entry>Version</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry>off</entry>
-      <entry>0</entry>
-     </row>
-
-     <row>
-      <entry>on</entry>
-      <entry>1</entry>
-     </row>
-
-     <row>
-      <entry>inprogress-off</entry>
-      <entry>2</entry>
-     </row>
-
-     <row>
-      <entry>inprogress-on</entry>
-      <entry>3</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
   <para>
    When attempting to recover from page corruptions, it may be necessary to
    bypass the checksum protection. To do this, temporarily set the
@@ -314,126 +274,11 @@
    <para>
     The <link linkend="app-pgchecksums"><application>pg_checksums</application></link>
     application can be used to enable or disable data checksums, as well as
-    verify checksums, on an offline cluster.
-   </para>
-
-  </sect2>
-
-  <sect2 id="checksums-online-enable-disable" xreflabel="Online Enabling of Checksums">
-   <title>Online Enabling of Checksums</title>
-
-   <para>
-    Checksums can be enabled or disabled online, by calling the appropriate
-    <link linkend="functions-admin-checksum">functions</link>.
-   </para>
-
-   <para>
-    Both enabling and disabling data checksums happens in two phases, separated
-    by a checkpoint to ensure durability.  The different states, and their
-    transitions, are illustrated in <xref linkend="data-checksums-states-figure"/>
-    and discussed in further detail in this section.
-   </para>
-
-   <para>
-    <figure id="data-checksums-states-figure">
-     <title>Data Checksums States</title>
-     <mediaobject>
-      <imageobject>
-       <imagedata fileref="images/datachecksums.svg" format="SVG" width="100%"/>
-      </imageobject>
-     </mediaobject>
-    </figure>
-   </para>
-
-   <para>
-    Enabling checksums will set the cluster checksum state to
-    <literal>inprogress-on</literal>.  During this time, checksums will be
-    written but not verified. In addition to this, a background worker process
-    is started that enables checksums on all existing data in the cluster. Once
-    this worker has completed processing all databases in the cluster, the
-    checksum state will automatically switch to <literal>on</literal>. The
-    processing will consume two background worker processes, make sure that
-    <varname>max_worker_processes</varname> allows for at least two more
-    additional processes.
-   </para>
-
-   <para>
-    The process will initially wait for all open transactions to finish before
-    it starts, so that it can be certain that there are no tables that have been
-    created inside a transaction that has not committed yet and thus would not
-    be visible to the process enabling checksums. It will also, for each database,
-    wait for all pre-existing temporary tables to get removed before it finishes.
-    If long-lived temporary tables are used in an application it may be necessary
-    to terminate these application connections to allow the process to complete.
+    verify checksums, on an offline cluster.  The same operation must be
+    executed on every node in a replicated cluster before the cluster is
+    restarted.
    </para>
 
-   <para>
-    If the cluster is stopped while in <literal>inprogress-on</literal> state,
-    for any reason, or processing was interrupted, then the checksum enable
-    process must be restarted manually.  To do this, re-execute the function
-    <function>pg_enable_data_checksums()</function> once the cluster has been
-    restarted.  The process will start over, there is no support for resuming
-    work from where it was interrupted.  If the cluster is stopped while in
-    <literal>inprogress-off</literal>, then the checksum state will be set to
-    <literal>off</literal> when the cluster is restarted.
-   </para>
-
-   <para>
-    Disabling data checksums will set the data checksum state to
-    <literal>inprogress-off</literal>.  During this time, checksums will be
-    written but not verified.  After all processes acknowledge the change,
-    the state will automatically be set to <literal>off</literal>.
-   </para>
-
-   <para>
-    Disabling data checksums while data checksums are actively being enabled
-    will abort the current processing.
-   </para>
-
-   <sect3 id="checksums-online-system-impact">
-    <title>Impact on System of Online Operations</title>
-    <para>
-     Enabling data checksums can cause significant I/O to the system, as all of the
-     database pages will need to be rewritten, and will be written both to the
-     data files and the WAL. The impact may be limited by throttling using the
-     <parameter>cost_delay</parameter> and <parameter>cost_limit</parameter>
-     parameters of the <function>pg_enable_data_checksums()</function> function.
-    </para>
-
-    <para>
-     <itemizedlist>
-      <listitem><para>
-       I/O: all pages need to have data checksums calculated and written which
-       will generate a lot of dirty pages that will need to be flushed to disk,
-       as well as WAL logged.
-      </para></listitem>
-      <listitem><para>
-       Replication: When the standby receives the data checksum state change
-       in the WAL stream it will issue a <glossterm linkend="glossary-restartpoint">
-       restartpoint</glossterm> in order to flush the current state into the
-       <filename>pg_control</filename> file.  The restartpoint will flush the
-       current state to disk and will block redo until finished.  This in turn
-       will induce replication lag, which on synchronous standbys also blocks
-       the primary.  Reducing <xref linkend="guc-max-wal-size"/> before the
-       process is started can help with reducing the time it takes for the
-       restartpoint to finish.
-      </para></listitem>
-      <listitem><para>
-       Shutdown/Restart: If the server is shut down or restarted when data
-       checksums are being enabled, the process will not resume and all pages
-       need to be recalculated and rewritten.  Enabling data checksums should
-       be done when there is no need for regular maintenance or during a
-       service window.
-      </para></listitem>
-     </itemizedlist>
-    </para>
-
-    <para>
-     No I/O is incurred when disabling data checksums, but checkpoints are
-     still required.
-    </para>
-   </sect3>
-
   </sect2>
  </sect1>
 
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 2468a7d2578..437bb0ab43c 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -55,40 +55,6 @@ get_wal_level_string(int wal_level)
 	return wal_level_str;
 }
 
-const char *
-get_checksum_state_string(uint32 state)
-{
-	switch (state)
-	{
-		case PG_DATA_CHECKSUM_VERSION:
-			return "on";
-		case PG_DATA_CHECKSUM_INPROGRESS_OFF:
-			return "inprogress-off";
-		case PG_DATA_CHECKSUM_INPROGRESS_ON:
-			return "inprogress-on";
-		case PG_DATA_CHECKSUM_OFF:
-			return "off";
-	}
-
-	Assert(false);
-	return "?";
-}
-
-void
-xlog2_desc(StringInfo buf, XLogReaderState *record)
-{
-	char	   *rec = XLogRecGetData(record);
-	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
-
-	if (info == XLOG2_CHECKSUMS)
-	{
-		xl_checksum_state xlrec;
-
-		memcpy(&xlrec, rec, sizeof(xl_checksum_state));
-		appendStringInfoString(buf, get_checksum_state_string(xlrec.new_checksum_state));
-	}
-}
-
 void
 xlog_desc(StringInfo buf, XLogReaderState *record)
 {
@@ -104,8 +70,7 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 						 "tli %u; prev tli %u; fpw %s; wal_level %s; logical decoding %s; xid %u:%u; oid %u; multi %u; offset %" PRIu64 "; "
 						 "oldest xid %u in DB %u; oldest multi %u in DB %u; "
 						 "oldest/newest commit timestamp xid: %u/%u; "
-						 "oldest running xid %u; "
-						 "checksums %s; %s",
+						 "oldest running xid %u; %s",
 						 LSN_FORMAT_ARGS(checkpoint->redo),
 						 checkpoint->ThisTimeLineID,
 						 checkpoint->PrevTimeLineID,
@@ -124,7 +89,6 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 						 checkpoint->oldestCommitTsXid,
 						 checkpoint->newestCommitTsXid,
 						 checkpoint->oldestActiveXid,
-						 get_checksum_state_string(checkpoint->dataChecksumState),
 						 (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
 	}
 	else if (info == XLOG_NEXTOID)
@@ -203,9 +167,8 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 		xl_checkpoint_redo xlrec;
 
 		memcpy(&xlrec, rec, sizeof(xl_checkpoint_redo));
-		appendStringInfo(buf, "wal_level %s; checksums %s",
-						 get_wal_level_string(xlrec.wal_level),
-						 get_checksum_state_string(xlrec.data_checksum_version));
+		appendStringInfo(buf, "wal_level %s",
+						 get_wal_level_string(xlrec.wal_level));
 	}
 	else if (info == XLOG_LOGICAL_DECODING_STATUS_CHANGE)
 	{
@@ -280,21 +243,6 @@ xlog_identify(uint8 info)
 	return id;
 }
 
-const char *
-xlog2_identify(uint8 info)
-{
-	const char *id = NULL;
-
-	switch (info & ~XLR_INFO_MASK)
-	{
-		case XLOG2_CHECKSUMS:
-			id = "CHECKSUMS";
-			break;
-	}
-
-	return id;
-}
-
 /*
  * Returns a string giving information about all the blocks in an
  * XLogRecord.
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7f5d3b1417a..00d3351dd86 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -75,7 +75,6 @@
 #include "pgstat.h"
 #include "port/atomics.h"
 #include "postmaster/bgwriter.h"
-#include "postmaster/datachecksum_state.h"
 #include "postmaster/startup.h"
 #include "postmaster/walsummarizer.h"
 #include "postmaster/walwriter.h"
@@ -93,7 +92,6 @@
 #include "storage/predicate.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
-#include "storage/procsignal.h"
 #include "storage/reinit.h"
 #include "storage/spin.h"
 #include "storage/subsystems.h"
@@ -556,18 +554,7 @@ typedef struct XLogCtlData
 	 */
 	XLogRecPtr	lastFpwDisableRecPtr;
 
-	/* last data_checksum_version we've seen */
-	uint32		data_checksum_version;
-
 	slock_t		info_lck;		/* locks shared variables shown above */
-
-	/*
-	 * lastChecksumChangeRecPtr points to the end of the last XLOG2_CHECKSUMS
-	 * record inserted or replayed, i.e. the last change of
-	 * data_checksum_version.  InvalidXLogRecPtr if the state hasn't changed
-	 * since the server started.
-	 */
-	pg_atomic_uint64 lastChecksumChangeRecPtr;
 } XLogCtlData;
 
 /*
@@ -675,21 +662,6 @@ static XLogRecPtr LocalMinRecoveryPoint;
 static TimeLineID LocalMinRecoveryPointTLI;
 static bool updateMinRecoveryPoint = true;
 
-/*
- * Local state for ControlFile data_checksum_version.  After initialization
- * this is only updated when absorbing a procsignal barrier during interrupt
- * processing.  The reason for keeping a copy in backend-private memory is to
- * avoid locking for interrogating the data checksum state.  Possible values
- * are the data checksum versions defined in storage/checksum.h.
- */
-static ChecksumStateType LocalDataChecksumState = 0;
-
-/*
- * Variable backing the GUC, keep it in sync with LocalDataChecksumState.
- * See SetLocalDataChecksumState().
- */
-int			data_checksums = 0;
-
 /* For WALInsertLockAcquire/Release functions */
 static int	MyLockNo = 0;
 static bool holdingAllLocks = false;
@@ -757,8 +729,6 @@ static void WALInsertLockAcquireExclusive(void);
 static void WALInsertLockRelease(void);
 static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
 
-static void XLogChecksums(uint32 new_type);
-
 /*
  * Insert an XLOG record represented by an already-constructed chain of data
  * chunks.  This is a low-level routine; to construct the WAL record header
@@ -4292,13 +4262,6 @@ InitControlFile(uint64 sysidentifier, uint32 data_checksum_version)
 	ControlFile->wal_log_hints = wal_log_hints;
 	ControlFile->track_commit_timestamp = track_commit_timestamp;
 	ControlFile->data_checksum_version = data_checksum_version;
-	ControlFile->data_checksum_version_init = data_checksum_version;
-
-	/*
-	 * Set the data_checksum_version value into XLogCtl, which is where all
-	 * processes get the current value from.
-	 */
-	XLogCtl->data_checksum_version = data_checksum_version;
 }
 
 static void
@@ -4633,6 +4596,10 @@ ReadControlFile(void)
 		(SizeOfXLogLongPHD - SizeOfXLogShortPHD);
 
 	CalculateCheckpointSegments();
+
+	/* Make the initdb settings visible as GUC variables, too */
+	SetConfigOption("data_checksums", DataChecksumsEnabled() ? "yes" : "no",
+					PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
 }
 
 /*
@@ -4666,347 +4633,13 @@ GetMockAuthenticationNonce(void)
 }
 
 /*
- * DataChecksumsNeedWrite
- *		Returns whether data checksums must be written or not
- *
- * Returns true if data checksums are enabled, or are in the process of being
- * enabled. During "inprogress-on" and "inprogress-off" states checksums must
- * be written even though they are not verified (see datachecksum_state.c for
- * a longer discussion).
- *
- * This function is intended for callsites which are about to write a data page
- * to storage, and need to know whether to re-calculate the checksum for the
- * page header. Calling this function must be performed as close to the write
- * operation as possible to keep the critical section short.
+ * Are checksums enabled for data pages?
  */
 bool
-DataChecksumsNeedWrite(void)
-{
-	return (LocalDataChecksumState == PG_DATA_CHECKSUM_VERSION ||
-			LocalDataChecksumState == PG_DATA_CHECKSUM_INPROGRESS_ON ||
-			LocalDataChecksumState == PG_DATA_CHECKSUM_INPROGRESS_OFF);
-}
-
-
-bool
-DataChecksumsOff(void)
-{
-	bool		ret;
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-	ret = (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_OFF);
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	return ret;
-}
-
-bool
-DataChecksumsOn(void)
-{
-	bool		ret;
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-	ret = (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_VERSION);
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	return ret;
-}
-
-bool
-DataChecksumsInProgressOn(void)
-{
-	bool		ret;
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-	ret = (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_INPROGRESS_ON);
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	return ret;
-}
-
-/*
- * DataChecksumsNeedVerify
- *		Returns whether data checksums must be verified or not
- *
- * Data checksums are only verified if they are fully enabled in the cluster.
- * During the "inprogress-on" and "inprogress-off" states they are only
- * updated, not verified (see datachecksum_state.c for a longer discussion).
- *
- * This function is intended for callsites which have read data and are about
- * to perform checksum validation based on the result of this.  Calling this
- * function must be performed as close to the validation call as possible to
- * keep the critical section short. This is in order to protect against time of
- * check/time of use situations around data checksum validation.
- */
-bool
-DataChecksumsNeedVerify(void)
-{
-	return (LocalDataChecksumState == PG_DATA_CHECKSUM_VERSION);
-}
-
-/*
- * GetLastChecksumChangeRecPtr
- *		Returns the location of the last data checksum state change
- *
- * Offline state changes by pg_checksums leave no trace here; callers must
- * also inspect the current state.
- *
- * No barrier semantics are needed: pages reach disk under a new checksum
- * state only after their writer absorbed the procsignal barrier for the
- * change, which is emitted after the new location became visible.
- */
-XLogRecPtr
-GetLastChecksumChangeRecPtr(void)
-{
-	return pg_atomic_read_u64(&XLogCtl->lastChecksumChangeRecPtr);
-}
-
-/*
- * SetDataChecksumsOnInProgress
- *		Sets the data checksum state to "inprogress-on" to enable checksums
- *
- * To start the process of enabling data checksums in a running cluster the
- * data_checksum_version state must be changed to "inprogress-on". See
- * SetDataChecksumsOn below for a description on how this state change works.
- * This function blocks until all backends in the cluster have acknowledged the
- * state transition.
- */
-void
-SetDataChecksumsOnInProgress(void)
-{
-	uint64		barrier;
-
-	/*
-	 * The state transition is performed in a critical section with
-	 * checkpoints held off to provide crash safety.
-	 */
-	START_CRIT_SECTION();
-	MyProc->delayChkptFlags |= DELAY_CHKPT_START;
-
-	XLogChecksums(PG_DATA_CHECKSUM_INPROGRESS_ON);
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-	XLogCtl->data_checksum_version = PG_DATA_CHECKSUM_INPROGRESS_ON;
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-	ControlFile->data_checksum_version = PG_DATA_CHECKSUM_INPROGRESS_ON;
-	UpdateControlFile();
-	LWLockRelease(ControlFileLock);
-
-	barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON);
-
-	MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
-	END_CRIT_SECTION();
-
-	WaitForProcSignalBarrier(barrier);
-}
-
-/*
- * SetDataChecksumsOn
- *		Set data checksums state to 'on' cluster-wide
- *
- * Enabling data checksums is performed using two barriers, the first one to
- * set the state to "inprogress-on" (done by SetDataChecksumsOnInProgress())
- * and the second one to set the state to "on" (done here). Below is a short
- * description of the processing, a more detailed write-up can be found in
- * datachecksum_state.c.
- *
- * To start the process of enabling data checksums in a running cluster the
- * data_checksum_version state must be changed to "inprogress-on".  This state
- * requires data checksums to be written but not verified. This ensures that
- * all data pages can be checksummed without the risk of false negatives in
- * validation during the process.  When all existing pages are guaranteed to
- * have checksums, and all new pages will be initiated with checksums, the
- * state can be changed to "on". Once the state is "on" checksums will be both
- * written and verified.
- *
- * This function blocks until all backends in the cluster have acknowledged the
- * state transition.
- */
-void
-SetDataChecksumsOn(void)
+DataChecksumsEnabled(void)
 {
-	uint64		barrier;
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-
-	/*
-	 * The only allowed state transition to "on" is from "inprogress-on" since
-	 * that state ensures that all pages will have data checksums written. Any
-	 * other attempted state transition is likely due to a programmer error.
-	 */
-	if (XLogCtl->data_checksum_version != PG_DATA_CHECKSUM_INPROGRESS_ON)
-	{
-		SpinLockRelease(&XLogCtl->info_lck);
-		elog(WARNING,
-			 "cannot set data checksums to \"on\", current state is not \"inprogress-on\", disabling");
-		SetDataChecksumsOff();
-		return;
-	}
-
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	INJECTION_POINT("datachecksums-enable-checksums-delay", NULL);
-	START_CRIT_SECTION();
-	MyProc->delayChkptFlags |= DELAY_CHKPT_START;
-
-	XLogChecksums(PG_DATA_CHECKSUM_VERSION);
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-	XLogCtl->data_checksum_version = PG_DATA_CHECKSUM_VERSION;
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	/*
-	 * Update the controlfile before waiting since if we have an immediate
-	 * shutdown while waiting we want to come back up with checksums enabled.
-	 */
-	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-	ControlFile->data_checksum_version = PG_DATA_CHECKSUM_VERSION;
-	UpdateControlFile();
-	LWLockRelease(ControlFileLock);
-
-	barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_ON);
-
-	MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
-	END_CRIT_SECTION();
-
-	INJECTION_POINT("datachecksums-on-before-checkpoint", NULL);
-
-	RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
-	WaitForProcSignalBarrier(barrier);
-}
-
-/*
- * SetDataChecksumsOff
- *		Disables data checksums cluster-wide
- *
- * Disabling data checksums must be performed with two sets of barriers, each
- * carrying a different state. The state is first set to "inprogress-off"
- * during which checksums are still written but not verified. This ensures that
- * backends which have yet to observe the state change from "on" won't get
- * validation errors on concurrently modified pages. Once all backends have
- * changed to "inprogress-off", the barrier for moving to "off" can be emitted.
- * This function blocks until all backends in the cluster have acknowledged the
- * state transition.
- */
-void
-SetDataChecksumsOff(void)
-{
-	uint64		barrier;
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-
-	/* If data checksums are already disabled there is nothing to do */
-	if (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_OFF)
-	{
-		SpinLockRelease(&XLogCtl->info_lck);
-		return;
-	}
-
-	/*
-	 * If data checksums are currently enabled, or in the process of being
-	 * enabled, we first transition to the "inprogress-off" state during which
-	 * backends continue to write checksums without verifying them. When all
-	 * backends are in "inprogress-off" the next transition to "off" can be
-	 * performed, after which all data checksum processing is disabled.
-	 */
-	if (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_VERSION ||
-		XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_INPROGRESS_ON)
-	{
-		SpinLockRelease(&XLogCtl->info_lck);
-
-		START_CRIT_SECTION();
-		MyProc->delayChkptFlags |= DELAY_CHKPT_START;
-
-		XLogChecksums(PG_DATA_CHECKSUM_INPROGRESS_OFF);
-
-		SpinLockAcquire(&XLogCtl->info_lck);
-		XLogCtl->data_checksum_version = PG_DATA_CHECKSUM_INPROGRESS_OFF;
-		SpinLockRelease(&XLogCtl->info_lck);
-
-		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-		ControlFile->data_checksum_version = PG_DATA_CHECKSUM_INPROGRESS_OFF;
-		UpdateControlFile();
-		LWLockRelease(ControlFileLock);
-
-		barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF);
-
-		MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
-		END_CRIT_SECTION();
-
-		RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
-		WaitForProcSignalBarrier(barrier);
-
-		/*
-		 * At this point we know that no backends are verifying data checksums
-		 * during reading. Next, we can safely move to state "off" to also
-		 * stop writing checksums.
-		 */
-	}
-	else
-	{
-		/*
-		 * Ending up here implies that the checksums state is "inprogress-off"
-		 * and we can transition directly to "off" from there.
-		 */
-		SpinLockRelease(&XLogCtl->info_lck);
-	}
-
-	START_CRIT_SECTION();
-	/* Ensure that we don't incur a checkpoint during disabling checksums */
-	MyProc->delayChkptFlags |= DELAY_CHKPT_START;
-
-	XLogChecksums(PG_DATA_CHECKSUM_OFF);
-
-	SpinLockAcquire(&XLogCtl->info_lck);
-	XLogCtl->data_checksum_version = PG_DATA_CHECKSUM_OFF;
-	SpinLockRelease(&XLogCtl->info_lck);
-
-	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-	ControlFile->data_checksum_version = PG_DATA_CHECKSUM_OFF;
-	UpdateControlFile();
-	LWLockRelease(ControlFileLock);
-
-	barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_OFF);
-
-	MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
-	END_CRIT_SECTION();
-
-	RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
-	WaitForProcSignalBarrier(barrier);
-}
-
-/*
- * InitLocalDataChecksumState
- *
- * Set up backend local caches of controldata variables which may change at
- * any point during runtime and thus require special cased locking. So far
- * this only applies to data_checksum_version, but it's intended to be general
- * purpose enough to handle future cases.
- */
-void
-InitLocalDataChecksumState(void)
-{
-	Assert(InterruptHoldoffCount > 0);
-	SpinLockAcquire(&XLogCtl->info_lck);
-	SetLocalDataChecksumState(XLogCtl->data_checksum_version);
-	SpinLockRelease(&XLogCtl->info_lck);
-}
-
-void
-SetLocalDataChecksumState(uint32 data_checksum_version)
-{
-	LocalDataChecksumState = data_checksum_version;
-
-	data_checksums = data_checksum_version;
-}
-
-/* guc hook */
-const char *
-show_data_checksums(void)
-{
-	return get_checksum_state_string(LocalDataChecksumState);
+	Assert(ControlFile != NULL);
+	return (ControlFile->data_checksum_version > 0);
 }
 
 /*
@@ -5301,7 +4934,6 @@ LocalProcessControlFile(bool reset)
 	LocalControlFile = palloc_object(ControlFileData);
 	ControlFile = LocalControlFile;
 	ReadControlFile();
-	SetLocalDataChecksumState(ControlFile->data_checksum_version);
 }
 
 /*
@@ -5453,17 +5085,12 @@ XLOGShmemInit(void *arg)
 	XLogCtl->InstallXLogFileSegmentActive = false;
 	XLogCtl->WalWriterSleeping = false;
 
-	/* Use the checksum info from control file */
-	XLogCtl->data_checksum_version = ControlFile->data_checksum_version;
-	SetLocalDataChecksumState(XLogCtl->data_checksum_version);
-
 	SpinLockInit(&XLogCtl->Insert.insertpos_lck);
 	SpinLockInit(&XLogCtl->info_lck);
 	pg_atomic_init_u64(&XLogCtl->logInsertResult, InvalidXLogRecPtr);
 	pg_atomic_init_u64(&XLogCtl->logWriteResult, InvalidXLogRecPtr);
 	pg_atomic_init_u64(&XLogCtl->logFlushResult, InvalidXLogRecPtr);
 	pg_atomic_init_u64(&XLogCtl->unloggedLSN, InvalidXLogRecPtr);
-	pg_atomic_init_u64(&XLogCtl->lastChecksumChangeRecPtr, InvalidXLogRecPtr);
 }
 
 /*
@@ -5541,7 +5168,6 @@ BootStrapXLOG(uint32 data_checksum_version)
 	checkPoint.newestCommitTsXid = InvalidTransactionId;
 	checkPoint.time = (pg_time_t) time(NULL);
 	checkPoint.oldestActiveXid = InvalidTransactionId;
-	checkPoint.dataChecksumState = data_checksum_version;
 
 	TransamVariables->nextXid = checkPoint.nextXid;
 	TransamVariables->nextOid = checkPoint.nextOid;
@@ -6620,50 +6246,6 @@ StartupXLOG(void)
 	pfree(endOfRecoveryInfo->recoveryStopReason);
 	pfree(endOfRecoveryInfo);
 
-	/*
-	 * If we reach this point with checksums in the state inprogress-on, it
-	 * means that data checksums were in the process of being enabled when the
-	 * cluster shut down. Since processing didn't finish, the operation will
-	 * have to be restarted from scratch since there is no capability to
-	 * continue where it was when the cluster shut down. Thus, revert the
-	 * state back to off, and inform the user with a warning message. Being
-	 * able to restart processing is a TODO, but it wouldn't be possible to
-	 * restart here since we cannot launch a dynamic background worker
-	 * directly from here (it has to be from a regular backend).
-	 */
-	if (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_INPROGRESS_ON)
-	{
-		XLogChecksums(PG_DATA_CHECKSUM_OFF);
-
-		SpinLockAcquire(&XLogCtl->info_lck);
-		XLogCtl->data_checksum_version = PG_DATA_CHECKSUM_OFF;
-		SetLocalDataChecksumState(XLogCtl->data_checksum_version);
-		SpinLockRelease(&XLogCtl->info_lck);
-
-		EmitAndWaitDataChecksumsBarrier(PG_DATA_CHECKSUM_OFF);
-		ereport(WARNING,
-				errmsg("enabling data checksums was interrupted"),
-				errhint("Data checksum processing must be manually restarted for checksums to be enabled."));
-	}
-
-	/*
-	 * If data checksums were being disabled when the cluster was shut down,
-	 * we know that we have a state where all backends have stopped validating
-	 * checksums and we can move to off instead of prompting the user to
-	 * perform any action.
-	 */
-	else if (XLogCtl->data_checksum_version == PG_DATA_CHECKSUM_INPROGRESS_OFF)
-	{
-		XLogChecksums(PG_DATA_CHECKSUM_OFF);
-
-		SpinLockAcquire(&XLogCtl->info_lck);
-		XLogCtl->data_checksum_version = PG_DATA_CHECKSUM_OFF;
-		SetLocalDataChecksumState(XLogCtl->data_checksum_version);
-		SpinLockRelease(&XLogCtl->info_lck);
-
-		EmitAndWaitDataChecksumsBarrier(PG_DATA_CHECKSUM_OFF);
-	}
-
 	/*
 	 * All done with end-of-recovery actions.
 	 *
@@ -6683,7 +6265,6 @@ StartupXLOG(void)
 	ControlFile->state = DB_IN_PRODUCTION;
 
 	SpinLockAcquire(&XLogCtl->info_lck);
-	ControlFile->data_checksum_version = XLogCtl->data_checksum_version;
 	XLogCtl->SharedRecoveryState = RECOVERY_STATE_DONE;
 	SpinLockRelease(&XLogCtl->info_lck);
 
@@ -6970,7 +6551,7 @@ GetRedoRecPtr(void)
 	XLogRecPtr	ptr;
 
 	/*
-	 * The possibly not up-to-date copy in XLogCtl is enough. Even if we
+	 * The possibly not up-to-date copy in XlogCtl is enough. Even if we
 	 * grabbed a WAL insertion lock to read the authoritative value in
 	 * Insert->RedoRecPtr, someone might update it just after we've released
 	 * the lock.
@@ -7548,14 +7129,6 @@ CreateCheckPoint(int flags)
 	checkPoint.fullPageWrites = Insert->fullPageWrites;
 	checkPoint.wal_level = wal_level;
 
-	/*
-	 * Get the current data_checksum_version value from xlogctl, valid at the
-	 * time of the checkpoint.
-	 */
-	SpinLockAcquire(&XLogCtl->info_lck);
-	checkPoint.dataChecksumState = XLogCtl->data_checksum_version;
-	SpinLockRelease(&XLogCtl->info_lck);
-
 	if (shutdown)
 	{
 		XLogRecPtr	curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
@@ -7612,9 +7185,6 @@ CreateCheckPoint(int flags)
 
 		WALInsertLockAcquire();
 		redo_rec.wal_level = wal_level;
-		SpinLockAcquire(&XLogCtl->info_lck);
-		redo_rec.data_checksum_version = XLogCtl->data_checksum_version;
-		SpinLockRelease(&XLogCtl->info_lck);
 		WALInsertLockRelease();
 
 		/* Include WAL level in record for WAL summarizer's benefit. */
@@ -7967,12 +7537,6 @@ CreateEndOfRecoveryRecord(void)
 	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 	ControlFile->minRecoveryPoint = recptr;
 	ControlFile->minRecoveryPointTLI = xlrec.ThisTimeLineID;
-
-	/* start with the latest checksum version (as of the end of recovery) */
-	SpinLockAcquire(&XLogCtl->info_lck);
-	ControlFile->data_checksum_version = XLogCtl->data_checksum_version;
-	SpinLockRelease(&XLogCtl->info_lck);
-
 	UpdateControlFile();
 	LWLockRelease(ControlFileLock);
 
@@ -8314,10 +7878,6 @@ CreateRestartPoint(int flags)
 			if (flags & CHECKPOINT_IS_SHUTDOWN)
 				ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY;
 		}
-
-		/* we shall start with the latest checksum version */
-		ControlFile->data_checksum_version = lastCheckPoint.dataChecksumState;
-
 		UpdateControlFile();
 	}
 	LWLockRelease(ControlFileLock);
@@ -8756,25 +8316,6 @@ XLogReportParameters(void)
 	}
 }
 
-/*
- * Log the new state of checksums
- */
-static void
-XLogChecksums(uint32 new_type)
-{
-	xl_checksum_state xlrec;
-	XLogRecPtr	recptr;
-
-	xlrec.new_checksum_state = new_type;
-
-	XLogBeginInsert();
-	XLogRegisterData((char *) &xlrec, sizeof(xl_checksum_state));
-
-	recptr = XLogInsert(RM_XLOG2_ID, XLOG2_CHECKSUMS);
-	pg_atomic_write_u64(&XLogCtl->lastChecksumChangeRecPtr, recptr);
-	XLogFlush(recptr);
-}
-
 /*
  * Update full_page_writes in shared memory, and write an
  * XLOG_FPW_CHANGE record if necessary.
@@ -8960,9 +8501,6 @@ xlog_redo(XLogReaderState *record)
 		/* ControlFile->checkPointCopy always tracks the latest ckpt XID */
 		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 		ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
-		ControlFile->data_checksum_version = checkPoint.dataChecksumState;
-
-		UpdateControlFile();
 		LWLockRelease(ControlFileLock);
 
 		/*
@@ -9199,20 +8737,7 @@ xlog_redo(XLogReaderState *record)
 	}
 	else if (info == XLOG_CHECKPOINT_REDO)
 	{
-		xl_checkpoint_redo redo_rec;
-		bool		new_state = false;
-
-		memcpy(&redo_rec, XLogRecGetData(record), sizeof(xl_checkpoint_redo));
-
-		SpinLockAcquire(&XLogCtl->info_lck);
-		XLogCtl->data_checksum_version = redo_rec.data_checksum_version;
-		SetLocalDataChecksumState(redo_rec.data_checksum_version);
-		if (redo_rec.data_checksum_version != ControlFile->data_checksum_version)
-			new_state = true;
-		SpinLockRelease(&XLogCtl->info_lck);
-
-		if (new_state)
-			EmitAndWaitDataChecksumsBarrier(redo_rec.data_checksum_version);
+		/* nothing to do here, just for informational purposes */
 	}
 	else if (info == XLOG_LOGICAL_DECODING_STATUS_CHANGE)
 	{
@@ -9265,64 +8790,6 @@ xlog_redo(XLogReaderState *record)
 	}
 }
 
-void
-xlog2_redo(XLogReaderState *record)
-{
-	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
-
-	if (info == XLOG2_CHECKSUMS)
-	{
-		xl_checksum_state state;
-		XLogRecPtr	lsn = record->EndRecPtr;
-
-		memcpy(&state, XLogRecGetData(record), sizeof(xl_checksum_state));
-
-		/* advertise the location before the new state becomes visible */
-		pg_atomic_write_u64(&XLogCtl->lastChecksumChangeRecPtr, lsn);
-
-		SpinLockAcquire(&XLogCtl->info_lck);
-		XLogCtl->data_checksum_version = state.new_checksum_state;
-		SpinLockRelease(&XLogCtl->info_lck);
-
-		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-		ControlFile->data_checksum_version = state.new_checksum_state;
-
-		/*
-		 * Update minRecoveryPoint to ensure that if recovery is aborted, we
-		 * recover back up to this point before allowing hot standby again.
-		 * The new state is durable in pg_control while its location is only
-		 * tracked in shared memory; a standby becoming consistent below this
-		 * record would let base backups resume checksum verification with the
-		 * location unknown.  The local copies cannot be updated as long as
-		 * crash recovery is happening and we expect all the WAL to be
-		 * replayed.
-		 */
-		if (InArchiveRecovery)
-		{
-			LocalMinRecoveryPoint = ControlFile->minRecoveryPoint;
-			LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI;
-		}
-		if (XLogRecPtrIsValid(LocalMinRecoveryPoint) && LocalMinRecoveryPoint < lsn)
-		{
-			TimeLineID	replayTLI;
-
-			(void) GetCurrentReplayRecPtr(&replayTLI);
-			ControlFile->minRecoveryPoint = lsn;
-			ControlFile->minRecoveryPointTLI = replayTLI;
-		}
-
-		UpdateControlFile();
-		LWLockRelease(ControlFileLock);
-
-		/*
-		 * Block on a procsignalbarrier to await all processes having seen the
-		 * change to checksum status. Once the barrier has been passed we can
-		 * initiate the corresponding processing.
-		 */
-		EmitAndWaitDataChecksumsBarrier(state.new_checksum_state);
-	}
-}
-
 /*
  * Return the extra open flags used for opening a file, depending on the
  * value of the GUCs wal_sync_method, fsync and debug_io_direct.
diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c
index 4dcb06942d1..8e26c4f8118 100644
--- a/src/backend/backup/basebackup.c
+++ b/src/backend/backup/basebackup.c
@@ -45,7 +45,6 @@
 #include "storage/reinit.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
-#include "utils/injection_point.h"
 #include "utils/ps_status.h"
 #include "utils/relcache.h"
 #include "utils/resowner.h"
@@ -108,7 +107,6 @@ static off_t read_file_data_into_buffer(bbsink *sink,
 										int *checksum_failures);
 static void push_to_sink(bbsink *sink, pg_checksum_context *checksum_ctx,
 						 size_t *bytes_done, void *data, size_t length);
-static bool backup_checksums_verifiable(XLogRecPtr start_lsn);
 static bool verify_page_checksum(Page page, XLogRecPtr start_lsn,
 								 BlockNumber blkno,
 								 uint16 *expected_checksum);
@@ -327,12 +325,6 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
 		/* notify basebackup sink about start of backup */
 		bbsink_begin_backup(sink, &state, SINK_BUFFER_LENGTH);
 
-		/*
-		 * Allow tests to hold the backup after the starting checkpoint but
-		 * before any file data is sent.
-		 */
-		INJECTION_POINT("basebackup-before-send-files", NULL);
-
 		/* Send off our tablespaces one by one */
 		foreach(lc, state.tablespaces)
 		{
@@ -1616,14 +1608,12 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
 	Assert((sink->bbs_buffer_length % BLCKSZ) == 0);
 
 	/*
-	 * Verify checksums unless the client requested otherwise, but only for
-	 * relation files, and only while checksums have been continuously enabled
-	 * since the checkpoint this backup started from.  Checksums can still be
-	 * disabled while the backup runs, thus we check at each point where we
-	 * could be validating a checksum.
+	 * If we weren't told not to verify checksums, and if checksums are
+	 * enabled for this cluster, and if this is a relation file, then verify
+	 * the checksum.
 	 */
-	if (!noverify_checksums && RelFileNumberIsValid(relfilenumber) &&
-		backup_checksums_verifiable(sink->bbs_state->startptr))
+	if (!noverify_checksums && DataChecksumsEnabled() &&
+		RelFileNumberIsValid(relfilenumber))
 		verify_checksum = true;
 
 	/*
@@ -1756,9 +1746,7 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
 		 * If the amount of data we were able to read was not a multiple of
 		 * BLCKSZ, we cannot verify checksums, which are block-level.
 		 */
-		if (verify_checksum &&
-			backup_checksums_verifiable(sink->bbs_state->startptr) &&
-			(cnt % BLCKSZ != 0))
+		if (verify_checksum && (cnt % BLCKSZ != 0))
 		{
 			ereport(WARNING,
 					(errmsg("could not verify checksum in file \"%s\", block "
@@ -1853,10 +1841,9 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
  * 'blkno' is the block number of the first page in the bbsink's buffer
  * relative to the start of the relation.
  *
- * 'verify_checksum' determines if the user has asked to verify checksums, but
- * since data checksums can be disabled, or become disabled, we need to check
- * state before verifying individual pages.  If we do this, we'll update
- * *checksum_failures and issue warnings as appropriate.
+ * 'verify_checksum' indicates whether we should try to verify checksums
+ * for the blocks we read. If we do this, we'll update *checksum_failures
+ * and issue warnings as appropriate.
  */
 static off_t
 read_file_data_into_buffer(bbsink *sink, const char *readfilename, int fd,
@@ -1882,13 +1869,6 @@ read_file_data_into_buffer(bbsink *sink, const char *readfilename, int fd,
 		int			reread_cnt;
 		uint16		expected_checksum;
 
-		/*
-		 * The data checksum state can change at any point, so we need to
-		 * re-check before each page.
-		 */
-		if (!backup_checksums_verifiable(sink->bbs_state->startptr))
-			return cnt;
-
 		page = sink->bbs_buffer + BLCKSZ * i;
 
 		/* If the page is OK, go on to the next one. */
@@ -1911,12 +1891,7 @@ read_file_data_into_buffer(bbsink *sink, const char *readfilename, int fd,
 		 * allows us to wait until we can be certain that no write to the
 		 * block is in progress. Since we don't have any such thing right now,
 		 * we just do this and hope for the best.
-		 *
-		 * The data checksum state may also have changed concurrently so check
-		 * again.
 		 */
-		if (!backup_checksums_verifiable(sink->bbs_state->startptr))
-			return cnt;
 		reread_cnt =
 			basebackup_read_file(fd, sink->bbs_buffer + BLCKSZ * i,
 								 BLCKSZ, offset + BLCKSZ * i,
@@ -2006,27 +1981,6 @@ push_to_sink(bbsink *sink, pg_checksum_context *checksum_ctx,
 	}
 }
 
-/*
- * Check whether data checksums can be verified for a backup started at
- * start_lsn.
- *
- * Checksums are verified only while they have been continuously enabled
- * since the checkpoint the backup started from: the state must be "on" and
- * the last state change must predate the backup start.  Such a checkpoint
- * guarantees that every page flushed before it has a checksum written.  Any
- * later state change ends verification for the rest of the backup: pages
- * written while checksums were off can lack checksums yet keep LSNs older
- * than the backup start, and re-enabling completes before the rewritten
- * pages are flushed, so observing the "on" state again is not enough to
- * resume.
- */
-static bool
-backup_checksums_verifiable(XLogRecPtr start_lsn)
-{
-	return DataChecksumsNeedVerify() &&
-		GetLastChecksumChangeRecPtr() <= start_lsn;
-}
-
 /*
  * Try to verify the checksum for the provided page, if it seems appropriate
  * to do so.
@@ -2052,35 +2006,9 @@ verify_page_checksum(Page page, XLogRecPtr start_lsn, BlockNumber blkno,
 	if (PageIsNew(page) || PageGetLSN(page) >= start_lsn)
 		return true;
 
-	if (!backup_checksums_verifiable(start_lsn))
-		return true;
-
 	/* Perform the actual checksum calculation. */
 	checksum = pg_checksum_page(page, blkno);
 
-#ifdef USE_INJECTION_POINTS
-	{
-		/*
-		 * Make it possible to test checksum verification failure without
-		 * having to destroy data on disk.  There is cap on how many times we
-		 * want to cause verification failure to make tests more interesting
-		 * and less log intensive.  This makes it easy to test pg_basebackup
-		 * with the command_checks_all test function.
-		 */
-		static int	hit = 0;
-
-		if (IS_INJECTION_POINT_ATTACHED("basebackup-fail-checksum-verification"))
-		{
-			if (hit++ < 5)
-			{
-				checksum = 0;
-				INJECTION_POINT_CACHED("basebackup-fail-checksum-verification",
-									   NULL);
-			}
-		}
-	}
-#endif
-
 	/* See whether it matches the value from the page. */
 	phdr = (PageHeader) page;
 	if (phdr->pd_checksum == checksum)
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 4427b2232b0..e49ff9c049d 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1472,25 +1472,6 @@ CREATE VIEW pg_stat_progress_copy AS
     FROM pg_stat_get_progress_info('COPY') AS S
         LEFT JOIN pg_database D ON S.datid = D.oid;
 
-CREATE VIEW pg_stat_progress_data_checksums AS
-    SELECT
-        S.pid AS pid, S.datid, D.datname AS datname,
-        CASE S.param1 WHEN 0 THEN 'enabling'
-                      WHEN 1 THEN 'disabling'
-                      WHEN 2 THEN 'waiting on temporary tables'
-					  WHEN 3 THEN 'waiting on barrier'
-                      WHEN 4 THEN 'done'
-                      END AS phase,
-        CASE S.param2 WHEN -1 THEN NULL ELSE S.param2 END AS databases_total,
-        CASE S.param3 WHEN -1 THEN NULL ELSE S.param3 END AS databases_done,
-        CASE S.param4 WHEN -1 THEN NULL ELSE S.param4 END AS relations_total,
-        CASE S.param5 WHEN -1 THEN NULL ELSE S.param5 END AS relations_done,
-        CASE S.param6 WHEN -1 THEN NULL ELSE S.param6 END AS blocks_total,
-        CASE S.param7 WHEN -1 THEN NULL ELSE S.param7 END AS blocks_done
-    FROM pg_stat_get_progress_info('DATACHECKSUMS') AS S
-        LEFT JOIN pg_database D ON S.datid = D.oid
-    ORDER BY S.datid; -- return the launcher process first
-
 CREATE VIEW pg_user_mappings AS
     SELECT
         U.oid       AS umid,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 600fc742a68..5ca1a299efd 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -559,23 +559,6 @@ CreateDatabaseUsingFileCopy(Oid src_dboid, Oid dst_dboid, Oid src_tsid,
 	Relation	rel;
 	HeapTuple	tuple;
 
-	/*
-	 * The strategy check in createdb() runs before our transaction has an XID
-	 * and before the pg_database row exists, so the datachecksumsworker
-	 * launcher can start in that window and miss both the new database and
-	 * our transaction, leaving the raw-copied files without checksums.
-	 */
-	if (DataChecksumsInProgressOn())
-		ereport(ERROR,
-				errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				errmsg("create database strategy \"%s\" not allowed when data checksums are being enabled",
-					   "file_copy"));
-
-	/*
-	 * The XID is assigned by now, so a datachecksumsworker launcher starting
-	 * after this point will wait for us and find the new database.
-	 */
-
 	/*
 	 * Force a checkpoint before starting the copy. This will force all dirty
 	 * buffers, including those of unlogged tables, out to disk, to ensure
@@ -1062,22 +1045,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
 		if (pg_strcasecmp(strategy, "wal_log") == 0)
 			dbstrategy = CREATEDB_WAL_LOG;
 		else if (pg_strcasecmp(strategy, "file_copy") == 0)
-		{
-			/*
-			 * If data checksums are being enabled we must not use file_copy
-			 * since it might copy source database which hasn't yet had data
-			 * checksums enabled, and the destination database will be skipped
-			 * as it's expected to have data checksums enabled.  Once we have
-			 * an XID assigned this needs to be rechecked, but if can error
-			 * out already we can save a lot of work.
-			 */
-			if (DataChecksumsInProgressOn())
-				ereport(ERROR,
-						errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						errmsg("create database strategy \"%s\" not allowed when data checksums are being enabled",
-							   strategy));
 			dbstrategy = CREATEDB_FILE_COPY;
-		}
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1883,8 +1851,6 @@ dropdb(const char *dbname, bool missing_ok, bool force)
 	systable_inplace_update_finish(inplace_state, tup);
 	XLogFlush(XactLastRecEnd);
 
-	INJECTION_POINT("dropdb-after-invalid-marker", NULL);
-
 	/*
 	 * Also delete the tuple - transactionally. If this transaction commits,
 	 * the row will be gone, but if we fail, dropdb() can be invoked again.
diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile
index 55044b2bc6f..0f4435d2d97 100644
--- a/src/backend/postmaster/Makefile
+++ b/src/backend/postmaster/Makefile
@@ -18,7 +18,6 @@ OBJS = \
 	bgworker.o \
 	bgwriter.o \
 	checkpointer.o \
-	datachecksum_state.o \
 	fork_process.o \
 	interrupt.o \
 	launch_backend.o \
diff --git a/src/backend/postmaster/auxprocess.c b/src/backend/postmaster/auxprocess.c
index ad4bf4bd2a8..2b8f45f0390 100644
--- a/src/backend/postmaster/auxprocess.c
+++ b/src/backend/postmaster/auxprocess.c
@@ -68,36 +68,8 @@ AuxiliaryProcessMainCommon(void)
 
 	BaseInit();
 
-	/*
-	 * Prevent consuming interrupts between setting ProcSignalInit and setting
-	 * the initial local data checksum value.  If a barrier is emitted, and
-	 * absorbed, before local cached state is initialized the state transition
-	 * can be invalid.
-	 */
-	HOLD_INTERRUPTS();
-
 	ProcSignalInit(NULL, 0);
 
-	/*
-	 * Initialize a local cache of the data_checksum_version, to be updated by
-	 * the procsignal-based barriers.
-	 *
-	 * This intentionally happens after initializing the procsignal, otherwise
-	 * we might miss a state change. This means we can get a barrier for the
-	 * state we've just initialized - but it can happen only once.
-	 *
-	 * The postmaster (which is what gets forked into the new child process)
-	 * does not handle barriers, therefore it may not have the current value
-	 * of LocalDataChecksumState value (it'll have the value read from the
-	 * control file, which may be arbitrarily old).
-	 *
-	 * NB: Even if the postmaster handled barriers, the value might still be
-	 * stale, as it might have changed after this process forked.
-	 */
-	InitLocalDataChecksumState();
-
-	RESUME_INTERRUPTS();
-
 	/*
 	 * Initialize the process-local logical info WAL logging state.
 	 *
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 4627f99dafb..884c0e76d8d 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -19,7 +19,6 @@
 #include "pgstat.h"
 #include "port/atomics.h"
 #include "postmaster/bgworker_internals.h"
-#include "postmaster/datachecksum_state.h"
 #include "postmaster/postmaster.h"
 #include "replication/logicallauncher.h"
 #include "replication/logicalworker.h"
@@ -158,14 +157,6 @@ static const struct
 	{
 		.fn_name = "TableSyncWorkerMain",
 		.fn_addr = TableSyncWorkerMain
-	},
-	{
-		.fn_name = "DataChecksumsWorkerLauncherMain",
-		.fn_addr = DataChecksumsWorkerLauncherMain
-	},
-	{
-		.fn_name = "DataChecksumsWorkerMain",
-		.fn_addr = DataChecksumsWorkerMain
 	}
 };
 
diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c
deleted file mode 100644
index 443cb799915..00000000000
--- a/src/backend/postmaster/datachecksum_state.c
+++ /dev/null
@@ -1,1979 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * datachecksum_state.c
- *	  Background worker for enabling or disabling data checksums online as
- *	  well as functionality for manipulating data checksum state
- *
- * When enabling data checksums on a cluster at initdb time or when shut down
- * with pg_checksums, no extra process is required as each page is checksummed,
- * and verified, when accessed.  When enabling checksums on an already running
- * cluster, this worker will ensure that all pages are checksummed before
- * verification of the checksums is turned on. In the case of disabling
- * checksums, the state transition is performed only in the control file, no
- * changes are performed on the data pages.
- *
- * Checksums can be either enabled or disabled cluster-wide, with on/off being
- * the end state for data_checksums.
- *
- * 1. Enabling checksums
- * ---------------------
- * When enabling checksums in an online cluster, data_checksums will be set to
- * "inprogress-on" which signals that write operations MUST compute and write
- * the checksum on the data page, but during reading the checksum SHALL NOT be
- * verified. This ensures that all objects created while checksums are being
- * enabled will have checksums set, but reads won't fail due to missing or
- * invalid checksums. Invalid checksums can be present in case the cluster had
- * checksums enabled, then disabled them and updated the page while they were
- * disabled.
- *
- * The DataChecksumsWorker will compile a list of all databases at the start,
- * any databases created concurrently will see the in-progress state and will
- * be checksummed automatically.  All databases from the original list MUST BE
- * successfully processed in order for data checksums to be enabled, the only
- * exception are databases which are dropped before having been processed.
- *
- * For each database, all relations which have storage are read and every data
- * page is marked dirty to force a write with the checksum. This will generate
- * a lot of WAL as the entire database is read and written.
- *
- * If the processing is interrupted by a cluster crash or restart, it needs to
- * be restarted from the beginning again as state isn't persisted.
- *
- * 2. Disabling checksums
- * ----------------------
- * When disabling checksums, data_checksums will be set to "inprogress-off"
- * which signals that checksums are written but no longer need to be verified.
- * This ensures that backends which have not yet transitioned to the
- * "inprogress-off" state will still see valid checksums on pages.
- *
- * 3. Synchronization and Correctness
- * ----------------------------------
- * The processes involved in enabling or disabling data checksums in an
- * online cluster must be properly synchronized with the normal backends
- * serving concurrent queries to ensure correctness. Correctness is defined
- * as the following:
- *
- *    - Backends SHALL NOT violate the data_checksums state they have agreed to
- *      by acknowledging the procsignalbarrier:  This means that all backends
- *      MUST calculate and write data checksums during all states except off;
- *      MUST validate checksums only in the 'on' state.
- *    - Data checksums SHALL NOT be considered enabled cluster-wide until all
- *      currently connected backends have state "on": This means that all
- *      backends must wait on the procsignalbarrier to be acknowledged by all
- *      before proceeding to validate data checksums.
- *
- * There are two steps of synchronization required for changing data_checksums
- * in an online cluster: (i) changing state in the active backends ("on",
- * "off", "inprogress-on" and "inprogress-off"), and (ii) ensuring no
- * incompatible objects and processes are left in a database when workers end.
- * The former deals with cluster-wide agreement on data checksum state and the
- * latter with ensuring that any concurrent activity cannot break the data
- * checksum contract during processing.
- *
- * Synchronizing the state change is done with procsignal barriers. Before
- * updating the data_checksums state in the control file, all other backends must absorb the
- * barrier.  Barrier absorption will happen during interrupt processing, which
- * means that connected backends will change state at different times.  If
- * waiting for a barrier is done during startup, for example during replay, it
- * is important to realize that any locks held by the startup process might
- * cause deadlocks if backends end up waiting for those locks while startup
- * is waiting for a procsignalbarrier.
- *
- * 3.1 When Enabling Data Checksums
- * --------------------------------
- * A process which fails to observe data checksums being enabled can induce two
- * types of errors: failing to write the checksum when modifying the page and
- * failing to validate the data checksum on the page when reading it.
- *
- * When processing starts all backends belong to one of the below sets, with
- * one of Bd and Bi being empty:
- *
- * Bg: Backend updating the global state and emitting the procsignalbarrier
- * Bd: Backends in "off" state
- * Bi: Backends in "inprogress-on" state
- *
- * If processing is started in an online cluster then all backends are in Bd.
- * If processing was halted by the cluster shutting down (due to a crash or
- * intentional restart), the controlfile state "inprogress-on" will be observed
- * on system startup and all backends will be placed in Bd. The controlfile
- * state will also be set to "off".
- *
- * Backends transition Bd -> Bi via a procsignalbarrier which is emitted by the
- * DataChecksumsWorkerLauncherMain.  When all backends have acknowledged the
- * barrier then Bd will be empty and the next phase can begin: calculating and
- * writing data checksums with DataChecksumsWorkers.  When the
- * DataChecksumsWorker processes have finished writing checksums on all pages,
- * data checksums are enabled cluster-wide via another procsignalbarrier.
- * There are four sets of backends where Bd shall be an empty set:
- *
- * Bg: Backend updating the global state and emitting the procsignalbarrier
- * Bd: Backends in "off" state
- * Be: Backends in "on" state
- * Bi: Backends in "inprogress-on" state
- *
- * Backends in Bi and Be will write checksums when modifying a page, but only
- * backends in Be will verify the checksum during reading. The Bg backend is
- * blocked waiting for all backends in Bi to process interrupts and move to
- * Be. Any backend starting while Bg is waiting on the procsignalbarrier will
- * observe the global state being "on" and will thus automatically belong to
- * Be.  Checksums are enabled cluster-wide when Bi is an empty set. Bi and Be
- * are compatible sets while still operating based on their local state as
- * both write data checksums.
- *
- * 3.2 When Disabling Data Checksums
- * ---------------------------------
- * A process which fails to observe that data checksums have been disabled
- * can induce two types of errors: writing the checksum when modifying the
- * page and validating a data checksum which is no longer correct due to
- * modifications to the page. The former is not an error per se as data
- * integrity is maintained, but it is wasteful.  The latter will cause errors
- * in user operations.  Assuming the following sets of backends:
- *
- * Bg: Backend updating the global state and emitting the procsignalbarrier
- * Bd: Backends in "off" state
- * Be: Backends in "on" state
- * Bo: Backends in "inprogress-off" state
- * Bi: Backends in "inprogress-on" state
- *
- * Backends transition from the Be state to Bd like so: Be -> Bo -> Bd.  From
- * all other states, the transition can be straight to Bd.
- *
- * The goal is to transition all backends to Bd making the others empty sets.
- * Backends in Bo write data checksums, but don't validate them, such that
- * backends still in Be can continue to validate pages until the barrier has
- * been absorbed such that they are in Bo. Once all backends are in Bo, the
- * barrier to transition to "off" can be raised and all backends can safely
- * stop writing data checksums as no backend is enforcing data checksum
- * validation any longer.
- *
- * 4. Future opportunities for optimizations
- * -----------------------------------------
- * Below are some potential optimizations and improvements which were brought
- * up during reviews of this feature, but which weren't implemented in the
- * initial version. These are ideas listed without any validation on their
- * feasibility or potential payoff. More discussion on (most of) these can be
- * found on the -hackers threads linked to in the commit message of this
- * feature.
- *
- *   * Launching datachecksumsworker for resuming operation from the startup
- *     process: Currently users have to restart processing manually after a
- *     restart since dynamic background worker cannot be started from the
- *     postmaster. Changing the startup process could make restarting the
- *     processing automatic on cluster restart.
- *   * Avoid dirtying the page when checksums already match: Iff the checksum
- *     on the page happens to already match we still dirty the page. It should
- *     be enough to only do the log_newpage_buffer() call in that case.
- *   * Teach pg_checksums to avoid checksummed pages when pg_checksums is used
- *     to enable checksums on a cluster which is in inprogress-on state and
- *     may have checksummed pages (make pg_checksums be able to resume an
- *     online operation). This should only be attempted for wal_level minimal.
- *   * Restartability (not necessarily with page granularity).
- *   * Avoid processing databases which were created during inprogress-on.
- *     Right now all databases are processed regardless to be safe.
- *   * Teach CREATE DATABASE to calculate checksums for databases created
- *     during inprogress-on with a template database which has yet to be
- *     processed.
- *
- *
- * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  src/backend/postmaster/datachecksum_state.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "access/genam.h"
-#include "access/heapam.h"
-#include "access/htup_details.h"
-#include "access/xact.h"
-#include "access/xlog.h"
-#include "access/xloginsert.h"
-#include "catalog/indexing.h"
-#include "catalog/pg_class.h"
-#include "catalog/pg_database.h"
-#include "commands/progress.h"
-#include "commands/vacuum.h"
-#include "common/relpath.h"
-#include "miscadmin.h"
-#include "pgstat.h"
-#include "postmaster/bgworker.h"
-#include "postmaster/bgwriter.h"
-#include "postmaster/datachecksum_state.h"
-#include "storage/bufmgr.h"
-#include "storage/checksum.h"
-#include "storage/ipc.h"
-#include "storage/latch.h"
-#include "storage/lmgr.h"
-#include "storage/lwlock.h"
-#include "storage/procarray.h"
-#include "storage/smgr.h"
-#include "storage/subsystems.h"
-#include "tcop/tcopprot.h"
-#include "utils/builtins.h"
-#include "utils/fmgroids.h"
-#include "utils/injection_point.h"
-#include "utils/lsyscache.h"
-#include "utils/ps_status.h"
-#include "utils/syscache.h"
-#include "utils/wait_event.h"
-
-/*
- * Configuration of conditions which must match when absorbing a procsignal
- * barrier during data checksum enable/disable operations.  A single function
- * is used for absorbing all barriers, and the current and target states must
- * be defined as a from/to tuple in the checksum_barriers struct.
- */
-typedef struct ChecksumBarrierCondition
-{
-	/* Current state of data checksums */
-	int			from;
-	/* Target state for data checksums */
-	int			to;
-} ChecksumBarrierCondition;
-
-static const ChecksumBarrierCondition checksum_barriers[9] =
-{
-	/*
-	 * Disabling checksums: If checksums are currently enabled, disabling must
-	 * go through the 'inprogress-off' state.
-	 */
-	{PG_DATA_CHECKSUM_VERSION, PG_DATA_CHECKSUM_INPROGRESS_OFF},
-	{PG_DATA_CHECKSUM_INPROGRESS_OFF, PG_DATA_CHECKSUM_OFF},
-
-	/*
-	 * If checksums are in the process of being enabled, but are not yet being
-	 * verified, we can abort by going back to 'off' state.
-	 */
-	{PG_DATA_CHECKSUM_INPROGRESS_ON, PG_DATA_CHECKSUM_OFF},
-
-	/*
-	 * Enabling checksums must normally go through the 'inprogress-on' state.
-	 */
-	{PG_DATA_CHECKSUM_OFF, PG_DATA_CHECKSUM_INPROGRESS_ON},
-	{PG_DATA_CHECKSUM_INPROGRESS_ON, PG_DATA_CHECKSUM_VERSION},
-
-	/*
-	 * If checksums are being disabled but all backends are still computing
-	 * checksums, we can go straight back to 'on'
-	 */
-	{PG_DATA_CHECKSUM_INPROGRESS_OFF, PG_DATA_CHECKSUM_VERSION},
-
-	/*
-	 * If checksums are being enabled when launcher_exit is executed, state is
-	 * set to off since we cannot reach on at that point.
-	 */
-	{PG_DATA_CHECKSUM_INPROGRESS_ON, PG_DATA_CHECKSUM_INPROGRESS_OFF},
-
-	/*
-	 * Transitions that can happen when a new request is made while another is
-	 * currently being processed.
-	 */
-	{PG_DATA_CHECKSUM_INPROGRESS_OFF, PG_DATA_CHECKSUM_INPROGRESS_ON},
-	{PG_DATA_CHECKSUM_OFF, PG_DATA_CHECKSUM_INPROGRESS_OFF},
-};
-
-/* Possible operations the DataChecksumsWorker can perform */
-typedef enum DataChecksumsWorkerOperation
-{
-	ENABLE_DATACHECKSUMS,
-	DISABLE_DATACHECKSUMS,
-} DataChecksumsWorkerOperation;
-
-/* Possible states for a database entry which has been processed */
-typedef enum
-{
-	DATACHECKSUMSWORKER_SUCCESSFUL = 0,
-	DATACHECKSUMSWORKER_ABORTED,
-	DATACHECKSUMSWORKER_FAILED,
-	DATACHECKSUMSWORKER_DROPDB,
-} DataChecksumsWorkerResult;
-
-/*
- * Signaling between backends calling pg_enable/disable_data_checksums, the
- * checksums launcher process, and the checksums worker process.
- *
- * This struct is protected by DataChecksumsWorkerLock
- */
-typedef struct DataChecksumsStateStruct
-{
-	/*
-	 * These are set by pg_{enable|disable}_data_checksums, to tell the
-	 * launcher what the target state is.
-	 */
-	DataChecksumsWorkerOperation launch_operation;
-	int			launch_cost_delay;
-	int			launch_cost_limit;
-
-	/*
-	 * Is a launcher process currently running?  This is set by the main
-	 * launcher process, after it has read the above launch_* parameters.
-	 */
-	bool		launcher_running;
-
-	/*
-	 * Every time a new worker is launched, it's assigned a unique invocation
-	 * number by incrementing this counter.
-	 */
-	uint64		worker_invocation_counter;
-
-	/*
-	 * Information about the current worker, if it's currently running.  These
-	 * are set by the worker launcher.
-	 */
-	uint64		worker_invocation;	/* unique invocation number */
-	Oid			database_oid;	/* database it's processing */
-	pid_t		worker_pid;		/* worker process's PID */
-
-	/*
-	 * These fields indicate the target state that the worker is currently
-	 * running with.  They can be different from the corresponding launch_*
-	 * fields, if a new pg_enable/disable_data_checksums() call was made while
-	 * the launcher/worker was already running.  The worker will periodically
-	 * check if new cost settings have been requested, and if so will copy
-	 * them from the launch_* fields and reset cost throttling to match the
-	 * new values.
-	 */
-	DataChecksumsWorkerOperation operation;
-	int			cost_delay;
-	int			cost_limit;
-
-	/*
-	 * Signaling between the launcher and the worker process. Protected by
-	 * DataChecksumsWorkerLock.
-	 */
-
-	/* result, set by worker before exiting */
-	DataChecksumsWorkerResult worker_result;
-
-	/*
-	 * Tells the worker process whether it should also process the shared
-	 * catalogs
-	 */
-	bool		process_shared_catalogs;
-} DataChecksumsStateStruct;
-
-/* Shared memory segment for datachecksumsworker */
-static DataChecksumsStateStruct *DataChecksumState;
-
-typedef struct DataChecksumsWorkerDatabase
-{
-	Oid			dboid;
-	char	   *dbname;
-} DataChecksumsWorkerDatabase;
-
-/* Flag set by the interrupt handler */
-static volatile sig_atomic_t abort_requested = false;
-
-static uint64 worker_invocation;
-
-/*
- * Have we set the DataChecksumsStateStruct->launcher_running flag?
- * If we have, we need to clear it before exiting!
- */
-static volatile sig_atomic_t launcher_running = false;
-
-/* Are we enabling data checksums, or disabling them? */
-static DataChecksumsWorkerOperation operation;
-
-/* Prototypes */
-static void StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
-											 int cost_delay,
-											 int cost_limit);
-static void ErrorOnInvalidDatabases(void);
-static bool ProcessSingleRelationFork(Relation reln, ForkNumber forkNum, BufferAccessStrategy strategy);
-static void ResetDataChecksumsProgressCounters(void);
-static bool ProcessSingleRelationByOid(Oid relationId, BufferAccessStrategy strategy);
-static BgwHandleStatus WaitForDataChecksumsWorkerState(BackgroundWorkerHandle *handle,
-													   bool wait_for_startup,
-													   pid_t *pidp,
-													   uint32 wait_event);
-static DataChecksumsWorkerResult ProcessDatabase(DataChecksumsWorkerDatabase *db);
-static void launcher_exit(int code, Datum arg);
-static void launcher_cancel_handler(SIGNAL_ARGS);
-static void WaitForAllTransactionsToFinish(void);
-static bool ProcessAllDatabases(void);
-static void DataChecksumsShmemRequest(void *arg);
-static bool DatabaseExists(Oid dboid);
-static List *BuildDatabaseList(void);
-static void FreeDatabaseList(List *dblist);
-static List *BuildRelationList(bool temp_relations, bool include_shared);
-
-const ShmemCallbacks DataChecksumsShmemCallbacks = {
-	.request_fn = DataChecksumsShmemRequest,
-};
-
-#define CHECK_FOR_LAUNCHER_ABORT_REQUEST() \
-	do {															\
-		Assert(MyBackendType == B_DATACHECKSUMSWORKER_LAUNCHER);	\
-		LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);			\
-		if (DataChecksumState->launch_operation != operation) 		\
-			abort_requested = true;									\
-		LWLockRelease(DataChecksumsWorkerLock);						\
-	} while (0)
-
-#define CHECK_FOR_WORKER_ABORT_REQUEST() \
-	do {															\
-		Assert(MyBackendType == B_DATACHECKSUMSWORKER_WORKER);		\
-		LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);			\
-		if (DataChecksumState->worker_invocation != worker_invocation || \
-			DataChecksumState->launch_operation != operation) 		\
-			abort_requested = true;									\
-		LWLockRelease(DataChecksumsWorkerLock);						\
-	} while (0)
-
-
-/*****************************************************************************
- * Functionality for manipulating the data checksum state in the cluster
- */
-
-void
-EmitAndWaitDataChecksumsBarrier(uint32 state)
-{
-	uint64		barrier;
-
-	switch (state)
-	{
-		case PG_DATA_CHECKSUM_INPROGRESS_ON:
-			barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON);
-			WaitForProcSignalBarrier(barrier);
-			break;
-
-		case PG_DATA_CHECKSUM_INPROGRESS_OFF:
-			barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF);
-			WaitForProcSignalBarrier(barrier);
-			break;
-
-		case PG_DATA_CHECKSUM_VERSION:
-			barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_ON);
-			WaitForProcSignalBarrier(barrier);
-			break;
-
-		case PG_DATA_CHECKSUM_OFF:
-			barrier = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_CHECKSUM_OFF);
-			WaitForProcSignalBarrier(barrier);
-			break;
-
-		default:
-			Assert(false);
-	}
-}
-
-/*
- * AbsorbDataChecksumsBarrier
- *		Generic function for absorbing data checksum state changes
- *
- * All procsignalbarriers regarding data checksum state changes are absorbed
- * with this function.  The set of conditions required for the state change to
- * be accepted are listed in the checksum_barriers struct, target_state is
- * used to look up the relevant entry.
- */
-bool
-AbsorbDataChecksumsBarrier(ProcSignalBarrierType barrier)
-{
-	uint32		target_state;
-	int			current = data_checksums;
-	bool		found = false;
-
-	/*
-	 * Translate the barrier condition to the target state, doing it here
-	 * instead of in the procsignal code saves the latter from knowing about
-	 * checksum states.
-	 */
-	switch (barrier)
-	{
-		case PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON:
-			target_state = PG_DATA_CHECKSUM_INPROGRESS_ON;
-			break;
-		case PROCSIGNAL_BARRIER_CHECKSUM_ON:
-			target_state = PG_DATA_CHECKSUM_VERSION;
-			break;
-		case PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF:
-			target_state = PG_DATA_CHECKSUM_INPROGRESS_OFF;
-			break;
-		case PROCSIGNAL_BARRIER_CHECKSUM_OFF:
-			target_state = PG_DATA_CHECKSUM_OFF;
-			break;
-		default:
-			elog(ERROR, "incorrect barrier \"%d\" received", barrier);
-	}
-
-	/*
-	 * If the target state matches the current state then the barrier has been
-	 * repeated.
-	 */
-	if (current == target_state)
-		return true;
-
-	/*
-	 * If the cluster is in recovery we skip the validation of current state
-	 * since the replay is trusted.
-	 */
-	if (RecoveryInProgress())
-	{
-		SetLocalDataChecksumState(target_state);
-		return true;
-	}
-
-	/*
-	 * Find the barrier condition definition for the target state. Not finding
-	 * a condition would be a grave programmer error as the states are a
-	 * discrete set.
-	 */
-	for (int i = 0; i < lengthof(checksum_barriers) && !found; i++)
-	{
-		if (checksum_barriers[i].from == current && checksum_barriers[i].to == target_state)
-			found = true;
-	}
-
-	/*
-	 * If the relevant state criteria aren't satisfied, throw an error which
-	 * will be caught by the procsignal machinery for a later retry.
-	 */
-	if (!found)
-		ereport(ERROR,
-				errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				errmsg("incorrect data checksum state %d for target state %d",
-					   current, target_state));
-
-	SetLocalDataChecksumState(target_state);
-	return true;
-}
-
-
-/*
- * Disables data checksums for the cluster, if applicable. Starts a background
- * worker which turns off the data checksums.
- */
-Datum
-disable_data_checksums(PG_FUNCTION_ARGS)
-{
-	PreventCommandDuringRecovery("pg_disable_data_checksums()");
-
-	if (!superuser())
-		ereport(ERROR,
-				errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				errmsg("must be superuser to change data checksum state"));
-
-	StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0);
-	PG_RETURN_VOID();
-}
-
-/*
- * Enables data checksums for the cluster, if applicable.  Supports vacuum-
- * like cost based throttling to limit system load. Starts a background worker
- * which updates data checksums on existing data.
- */
-Datum
-enable_data_checksums(PG_FUNCTION_ARGS)
-{
-	int			cost_delay = PG_GETARG_INT32(0);
-	int			cost_limit = PG_GETARG_INT32(1);
-
-	PreventCommandDuringRecovery("pg_enable_data_checksums()");
-
-	if (!superuser())
-		ereport(ERROR,
-				errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				errmsg("must be superuser to change data checksum state"));
-
-	if (cost_delay < 0)
-		ereport(ERROR,
-				errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				errmsg("cost delay cannot be a negative value"));
-
-	if (cost_limit <= 0)
-		ereport(ERROR,
-				errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				errmsg("cost limit must be greater than zero"));
-
-	/*
-	 * An invalid database cannot be connected to, so the worker would fail to
-	 * process it, and unlike a dropped database its files stay around.  Error
-	 * out early with a hint rather than failing halfway through processing. A
-	 * database which turns invalid after this check, for example from an
-	 * interrupted DROP DATABASE, instead makes its worker fail; the launcher
-	 * then aborts and leaves checksums disabled, since the invalid database's
-	 * files would otherwise be left without valid checksums.
-	 */
-	ErrorOnInvalidDatabases();
-
-	StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit);
-
-	PG_RETURN_VOID();
-}
-
-
-/*****************************************************************************
- * Functionality for running the datachecksumsworker and associated launcher
- */
-
-/*
- * StartDataChecksumsWorkerLauncher
- *		Start the datachecksumsworker launcher process, if not running yet
- *
- * This is called to start data checksums processing for enabling as well as
- * disabling.
- */
-static void
-StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
-								 int cost_delay,
-								 int cost_limit)
-{
-	BackgroundWorker bgw;
-	BackgroundWorkerHandle *bgw_handle;
-	bool		running;
-
-#ifdef USE_ASSERT_CHECKING
-	/* The cost delay settings have no effect when disabling */
-	if (op == DISABLE_DATACHECKSUMS)
-		Assert(cost_delay == 0 && cost_limit == 0);
-#endif
-
-	INJECTION_POINT("datachecksumsworker-startup-delay", NULL);
-
-	/* Store the desired state in shared memory */
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-
-	DataChecksumState->launch_operation = op;
-	DataChecksumState->launch_cost_delay = cost_delay;
-	DataChecksumState->launch_cost_limit = cost_limit;
-
-	/* Is the launcher already running? If so, what is it doing? */
-	running = DataChecksumState->launcher_running;
-
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	/*
-	 * Launch a new launcher process, if it's not running already.
-	 *
-	 * If the launcher is currently busy enabling the checksums, and we want
-	 * them disabled (or vice versa), the launcher will notice that at latest
-	 * when it's about to exit, and will loop back to process the new request.
-	 * So if the launcher is already running, we don't need to do anything
-	 * more here to abort it.
-	 *
-	 * If you call pg_enable/disable_data_checksums() twice in a row, before
-	 * the launcher has had a chance to start up, we still end up launching it
-	 * twice.  That's OK, the second invocation will see that a launcher is
-	 * already running and exit quickly.
-	 */
-	if (!running)
-	{
-		if ((op == ENABLE_DATACHECKSUMS && DataChecksumsOn()) ||
-			(op == DISABLE_DATACHECKSUMS && DataChecksumsOff()))
-		{
-			ereport(LOG,
-					errmsg("data checksums already in desired state, exiting"));
-			return;
-		}
-
-		/*
-		 * Prepare the BackgroundWorker and launch it.
-		 */
-		memset(&bgw, 0, sizeof(bgw));
-		bgw.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
-		bgw.bgw_start_time = BgWorkerStart_RecoveryFinished;
-		snprintf(bgw.bgw_library_name, BGW_MAXLEN, "postgres");
-		snprintf(bgw.bgw_function_name, BGW_MAXLEN, "DataChecksumsWorkerLauncherMain");
-		snprintf(bgw.bgw_name, BGW_MAXLEN, "datachecksums launcher");
-		snprintf(bgw.bgw_type, BGW_MAXLEN, "datachecksums launcher");
-		bgw.bgw_restart_time = BGW_NEVER_RESTART;
-		bgw.bgw_notify_pid = MyProcPid;
-		bgw.bgw_main_arg = (Datum) 0;
-
-		if (!RegisterDynamicBackgroundWorker(&bgw, &bgw_handle))
-			ereport(ERROR,
-					errcode(ERRCODE_INSUFFICIENT_RESOURCES),
-					errmsg("failed to start background worker to process data checksums"));
-	}
-	else
-	{
-		ereport(LOG,
-				errmsg("data checksum processing already running"));
-	}
-}
-
-/*
- * ProcessSingleRelationFork
- *		Enable data checksums in a single relation/fork.
- *
- * Returns true if successful, and false if *aborted*. On error, an actual
- * error is raised in the lower levels.
- */
-static bool
-ProcessSingleRelationFork(Relation reln, ForkNumber forkNum, BufferAccessStrategy strategy)
-{
-	BlockNumber numblocks = RelationGetNumberOfBlocksInFork(reln, forkNum);
-	char		activity[NAMEDATALEN * 2 + 128];
-	char	   *relns;
-
-	relns = get_namespace_name(RelationGetNamespace(reln));
-
-	/* Report the current relation to pg_stat_activity */
-	snprintf(activity, sizeof(activity) - 1, "processing: %s.%s (%s, %u blocks)",
-			 (relns ? relns : ""), RelationGetRelationName(reln), forkNames[forkNum], numblocks);
-	pgstat_report_activity(STATE_RUNNING, activity);
-	{
-		const int	index[] = {
-			PROGRESS_DATACHECKSUMS_BLOCKS_TOTAL,
-			PROGRESS_DATACHECKSUMS_BLOCKS_DONE
-		};
-
-		int64		vals[2];
-
-		vals[0] = numblocks;
-		vals[1] = 0;
-
-		pgstat_progress_update_multi_param(2, index, vals);
-	}
-	if (relns)
-		pfree(relns);
-
-	/*
-	 * We are looping over the blocks which existed at the time of process
-	 * start, which is safe since new blocks are created with checksums set
-	 * already due to the state being "inprogress-on".
-	 */
-	for (BlockNumber blknum = 0; blknum < numblocks; blknum++)
-	{
-		Buffer		buf = ReadBufferExtended(reln, forkNum, blknum, RBM_NORMAL, strategy);
-
-		/* Need to get an exclusive lock to mark the buffer as dirty */
-		LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
-
-		/*
-		 * Mark the buffer as dirty and force a full page write.  We have to
-		 * re-write the page to WAL even if the checksum hasn't changed,
-		 * because if there is a replica it might have a slightly different
-		 * version of the page with an invalid checksum, caused by unlogged
-		 * changes (e.g. hint bits) on the primary happening while checksums
-		 * were off. This can happen if there was a valid checksum on the page
-		 * at one point in the past, so only when checksums are first on, then
-		 * off, and then turned on again.  TODO: investigate if this could be
-		 * avoided if the checksum is calculated to be correct and wal_level
-		 * is set to "minimal".
-		 *
-		 * Unlogged relations don't need WAL since they are reset to their
-		 * init fork on recovery.  We still dirty the buffer so that the
-		 * checksum is written to disk at the next checkpoint.
-		 *
-		 * The init fork is an exception: it is WAL-logged so the standby can
-		 * materialize the relation after promotion (see
-		 * ResetUnloggedRelations()).  Skipping it here would leave the
-		 * standby with a stale init fork that, once copied to the main fork
-		 * on promotion, would fail checksum verification on every read.
-		 */
-		START_CRIT_SECTION();
-		MarkBufferDirty(buf);
-		if (RelationNeedsWAL(reln) || forkNum == INIT_FORKNUM)
-			log_newpage_buffer(buf, false);
-		END_CRIT_SECTION();
-
-		UnlockReleaseBuffer(buf);
-
-		/* Check if we are asked to abort, the abortion will bubble up. */
-		Assert(operation == ENABLE_DATACHECKSUMS);
-		CHECK_FOR_WORKER_ABORT_REQUEST();
-		if (abort_requested)
-			return false;
-
-		/* update the block counter */
-		pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_BLOCKS_DONE,
-									 (blknum + 1));
-
-		/*
-		 * Processing is re-using the vacuum cost delay for process
-		 * throttling, hence why we call vacuum APIs here.
-		 */
-		vacuum_delay_point(false);
-	}
-
-	return true;
-}
-
-/*
- * Initialize all data checksum progress counters to be displayed as NULL.
- */
-static void
-ResetDataChecksumsProgressCounters(void)
-{
-	const int	index[] = {
-		PROGRESS_DATACHECKSUMS_DBS_TOTAL,
-		PROGRESS_DATACHECKSUMS_DBS_DONE,
-		PROGRESS_DATACHECKSUMS_RELS_TOTAL,
-		PROGRESS_DATACHECKSUMS_RELS_DONE,
-		PROGRESS_DATACHECKSUMS_BLOCKS_TOTAL,
-		PROGRESS_DATACHECKSUMS_BLOCKS_DONE,
-	};
-
-	int64		vals[lengthof(index)];
-
-	for (int i = 0; i < lengthof(index); i++)
-		vals[i] = -1;
-
-	pgstat_progress_update_multi_param(lengthof(index), index, vals);
-}
-
-/*
- * ProcessSingleRelationByOid
- *		Process a single relation based on oid.
- *
- * Returns true if successful, and false if *aborted*. On error, an actual
- * error is raised in the lower levels.
- */
-static bool
-ProcessSingleRelationByOid(Oid relationId, BufferAccessStrategy strategy)
-{
-	Relation	rel;
-	bool		aborted = false;
-
-	StartTransactionCommand();
-
-	rel = try_relation_open(relationId, AccessShareLock);
-	if (rel == NULL)
-	{
-		/*
-		 * Relation no longer exists. We don't consider this an error since
-		 * there are no pages in it that need data checksums, and thus return
-		 * true. The worker operates off a list of relations generated at the
-		 * start of processing, so relations being dropped in the meantime is
-		 * to be expected.
-		 */
-		CommitTransactionCommand();
-		pgstat_report_activity(STATE_IDLE, NULL);
-		return true;
-	}
-
-	for (ForkNumber fnum = 0; fnum <= MAX_FORKNUM; fnum++)
-	{
-		if (smgrexists(RelationGetSmgr(rel), fnum))
-		{
-			if (!ProcessSingleRelationFork(rel, fnum, strategy))
-			{
-				aborted = true;
-				break;
-			}
-		}
-	}
-	relation_close(rel, AccessShareLock);
-
-	CommitTransactionCommand();
-	pgstat_report_activity(STATE_IDLE, NULL);
-
-	return !aborted;
-}
-
-/*
- * WaitForDataChecksumsWorkerState
- *		Wait for a data checksums worker to start or stop.
- *
- * This is like WaitForBackgroundWorkerStartup() and
- * WaitForBackgroundWorkerShutdown(), except that it also reacts to SIGINT
- * received by the launcher.  The launcher owns the overall checksum
- * operation, so canceling it should stop the worker it has registered or is
- * currently running.
- *
- * If wait_for_startup is true, wait until the worker is no longer in
- * BGWH_NOT_YET_STARTED state, like WaitForBackgroundWorkerStartup().  If it
- * is false, wait until the worker reaches BGWH_STOPPED state, like
- * WaitForBackgroundWorkerShutdown().
- *
- * pidp is set to the worker's PID when startup succeeds, if it is not NULL.
- */
-static BgwHandleStatus
-WaitForDataChecksumsWorkerState(BackgroundWorkerHandle *handle,
-								bool wait_for_startup,
-								pid_t *pidp,
-								uint32 wait_event)
-{
-	BgwHandleStatus status;
-	bool		termination_requested = false;
-
-	for (;;)
-	{
-		int			rc;
-		pid_t		pid;
-
-		CHECK_FOR_INTERRUPTS();
-
-		status = GetBackgroundWorkerPid(handle, &pid);
-		if (status == BGWH_STARTED && pidp)
-			*pidp = pid;
-
-		if (abort_requested && !termination_requested)
-		{
-			TerminateBackgroundWorker(handle);
-			termination_requested = true;
-		}
-
-		/*
-		 * Startup waits for the worker to leave BGWH_NOT_YET_STARTED, while
-		 * shutdown waits for it to reach BGWH_STOPPED.
-		 */
-		if (status == BGWH_STOPPED ||
-			(wait_for_startup && status == BGWH_STARTED))
-			break;
-
-		rc = WaitLatch(MyLatch,
-					   WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
-					   wait_event);
-
-		if (rc & WL_POSTMASTER_DEATH)
-		{
-			status = BGWH_POSTMASTER_DIED;
-			break;
-		}
-
-		ResetLatch(MyLatch);
-	}
-
-	return status;
-}
-
-/*
- * ProcessDatabase
- *		Enable data checksums in a single database.
- *
- * We do this by launching a dynamic background worker into this database, and
- * waiting for it to finish.  We have to do this in a separate worker, since
- * each process can only be connected to one database during its lifetime.
- */
-static DataChecksumsWorkerResult
-ProcessDatabase(DataChecksumsWorkerDatabase *db)
-{
-	BackgroundWorker bgw;
-	BackgroundWorkerHandle *bgw_handle;
-	BgwHandleStatus status;
-	pid_t		pid;
-	uint64		invocation;
-	char		activity[NAMEDATALEN + 64];
-	DataChecksumsWorkerResult result;
-
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-
-	/*
-	 * Initialize result to FAILED.  The worker will change it to SUCCESSFUL
-	 * if it completes successfully.
-	 */
-	DataChecksumState->worker_result = DATACHECKSUMSWORKER_FAILED;
-	DataChecksumState->worker_pid = InvalidPid;
-
-	invocation = ++DataChecksumState->worker_invocation_counter;
-	DataChecksumState->worker_invocation = invocation;
-	DataChecksumState->database_oid = db->dboid;
-
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	memset(&bgw, 0, sizeof(bgw));
-	bgw.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
-	bgw.bgw_start_time = BgWorkerStart_RecoveryFinished;
-	snprintf(bgw.bgw_library_name, BGW_MAXLEN, "postgres");
-	snprintf(bgw.bgw_function_name, BGW_MAXLEN, "%s", "DataChecksumsWorkerMain");
-	snprintf(bgw.bgw_name, BGW_MAXLEN, "datachecksums worker");
-	snprintf(bgw.bgw_type, BGW_MAXLEN, "datachecksums worker");
-	bgw.bgw_restart_time = BGW_NEVER_RESTART;
-	bgw.bgw_notify_pid = MyProcPid;
-	/* pass the invocation number to the worker process */
-	bgw.bgw_main_arg = UInt64GetDatum(invocation);
-
-	/*
-	 * If there are no worker slots available, there is little we can do.  If
-	 * we retry in a bit it's still unlikely that the user has managed to
-	 * reconfigure in the meantime and we'd be run through retries fast.
-	 */
-	if (!RegisterDynamicBackgroundWorker(&bgw, &bgw_handle))
-	{
-		ereport(WARNING,
-				errmsg("could not start background worker for enabling data checksums in database \"%s\"",
-					   db->dbname),
-				errhint("The \"%s\" setting might be too low.", "max_worker_processes"));
-		return DATACHECKSUMSWORKER_FAILED;
-	}
-
-	/*
-	 * While this expects to wait for BGWORKER_STARTUP it may return _STOPPED
-	 * if the worker was terminated in the meantime so we must check status.
-	 */
-	status = WaitForDataChecksumsWorkerState(bgw_handle, true, &pid,
-											 WAIT_EVENT_BGWORKER_STARTUP);
-	if (status == BGWH_STOPPED)
-	{
-		if (abort_requested)
-		{
-			result = DATACHECKSUMSWORKER_ABORTED;
-			goto done;
-		}
-
-		/*
-		 * If the worker managed to start, and stop, before we got to waiting
-		 * for it we can see a STOPPED status here without it being a failure.
-		 */
-		LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);
-		Assert(DataChecksumState->worker_invocation == invocation);
-		if (DataChecksumState->worker_result == DATACHECKSUMSWORKER_SUCCESSFUL)
-		{
-			LWLockRelease(DataChecksumsWorkerLock);
-			pgstat_report_activity(STATE_IDLE, NULL);
-			return DATACHECKSUMSWORKER_SUCCESSFUL;
-		}
-		LWLockRelease(DataChecksumsWorkerLock);
-
-		ereport(WARNING,
-				errmsg("could not start background worker for enabling data checksums in database \"%s\"",
-					   db->dbname),
-				errhint("More details on the error might be found in the server log."));
-
-		/*
-		 * Heuristic to see if the database was dropped, and if it was we can
-		 * treat it as not an error, else treat as fatal and error out.
-		 */
-		if (DatabaseExists(db->dboid))
-			return DATACHECKSUMSWORKER_FAILED;
-		else
-			return DATACHECKSUMSWORKER_DROPDB;
-	}
-
-	/*
-	 * If the postmaster crashed we cannot end up with a processed database so
-	 * we have no alternative other than exiting. When enabling checksums we
-	 * won't at this time have changed the data checksums state in pg_control
-	 * to enabled so when the cluster comes back up processing will have to be
-	 * restarted.
-	 */
-	if (status == BGWH_POSTMASTER_DIED)
-		ereport(FATAL,
-				errcode(ERRCODE_ADMIN_SHUTDOWN),
-				errmsg("cannot enable data checksums without the postmaster process"),
-				errhint("Restart the database and restart data checksum processing by calling pg_enable_data_checksums()."));
-
-	Assert(status == BGWH_STARTED);
-	ereport(LOG,
-			errmsg("initiating data checksum processing in database \"%s\"",
-				   db->dbname));
-
-	/* Save the pid of the worker so we can signal it later */
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	Assert(DataChecksumState->worker_invocation == invocation);
-	DataChecksumState->worker_pid = pid;
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	snprintf(activity, sizeof(activity) - 1,
-			 "Waiting for worker in database %s (pid %ld)", db->dbname, (long) pid);
-	pgstat_report_activity(STATE_RUNNING, activity);
-
-	status = WaitForDataChecksumsWorkerState(bgw_handle, false, NULL,
-											 WAIT_EVENT_BGWORKER_SHUTDOWN);
-	if (status == BGWH_POSTMASTER_DIED)
-		ereport(FATAL,
-				errcode(ERRCODE_ADMIN_SHUTDOWN),
-				errmsg("postmaster exited during data checksum processing in \"%s\"",
-					   db->dbname),
-				errhint("Restart the database and restart data checksum processing by calling pg_enable_data_checksums()."));
-
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	Assert(DataChecksumState->worker_invocation == invocation);
-	result = DataChecksumState->worker_result;
-	DataChecksumState->worker_pid = InvalidPid;
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	/*
-	 * A worker which started but failed before reporting a result has most
-	 * likely FATALed in InitPostgres.  If the database was dropped after we
-	 * built the database list then that is the expected outcome and not an
-	 * error, so apply the same heuristic as when the worker failed to start.
-	 */
-	if (result == DATACHECKSUMSWORKER_FAILED && !DatabaseExists(db->dboid))
-		result = DATACHECKSUMSWORKER_DROPDB;
-
-	CHECK_FOR_LAUNCHER_ABORT_REQUEST();
-	if (abort_requested)
-		result = DATACHECKSUMSWORKER_ABORTED;
-
-done:
-	if (result == DATACHECKSUMSWORKER_ABORTED)
-		ereport(LOG,
-				errmsg("data checksums processing was aborted in database \"%s\"",
-					   db->dbname));
-	pgstat_report_activity(STATE_IDLE, NULL);
-	return result;
-}
-
-/*
- * launcher_exit
- *
- * Internal routine for cleaning up state when a launcher process which has
- * performed checksum operations exits. A launcher process which is exiting due
- * to a duplicate started launcher does not need to perform any cleanup and
- * this function should not be called. Otherwise, we need to clean up the abort
- * flag to ensure that processing can be started again if it was previously
- * aborted (note: started again, *not* restarted from where it left off).
- */
-static void
-launcher_exit(int code, Datum arg)
-{
-	abort_requested = false;
-
-	if (launcher_running)
-	{
-		LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-		if (DataChecksumState->worker_pid != InvalidPid)
-		{
-			ereport(LOG,
-					errmsg("data checksums launcher exiting while worker is still running, signalling worker"));
-			kill(DataChecksumState->worker_pid, SIGTERM);
-			DataChecksumState->worker_pid = InvalidPid;
-		}
-		LWLockRelease(DataChecksumsWorkerLock);
-	}
-
-	/*
-	 * If the launcher is exiting before data checksums are enabled then set
-	 * the state to off since processing cannot be resumed.
-	 */
-	if (DataChecksumsInProgressOn())
-		SetDataChecksumsOff();
-
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	launcher_running = false;
-	DataChecksumState->launcher_running = false;
-	LWLockRelease(DataChecksumsWorkerLock);
-}
-
-/*
- * launcher_cancel_handler
- *
- * Internal routine for reacting to SIGINT and flagging the launcher to abort.
- * If a worker is registered or running, the launcher will request worker
- * termination from its normal control flow.
- */
-static void
-launcher_cancel_handler(SIGNAL_ARGS)
-{
-	int			save_errno = errno;
-
-	abort_requested = true;
-
-	/*
-	 * Wake the launcher if it is waiting for transactions to finish or for a
-	 * worker to start up or shut down.
-	 */
-	SetLatch(MyLatch);
-
-	errno = save_errno;
-}
-
-/*
- * WaitForAllTransactionsToFinish
- *		Blocks awaiting all current transactions to finish
- *
- * Returns when all transactions which are active at the call of the function
- * have ended.
- *
- * NB: this will return early, if aborted by SIGINT or if the target state
- * is changed while we're running.
- */
-static void
-WaitForAllTransactionsToFinish(void)
-{
-	TransactionId waitforxid;
-
-	LWLockAcquire(XidGenLock, LW_SHARED);
-	waitforxid = XidFromFullTransactionId(TransamVariables->nextXid);
-	LWLockRelease(XidGenLock);
-
-	while (TransactionIdPrecedes(GetOldestActiveTransactionId(false, true), waitforxid))
-	{
-		char		activity[64];
-		int			rc;
-
-		/* Oldest running xid is older than us, so wait */
-		snprintf(activity,
-				 sizeof(activity),
-				 "Waiting for transactions older than %u to end",
-				 waitforxid);
-		pgstat_report_activity(STATE_RUNNING, activity);
-
-		/* Retry every 3 seconds */
-		ResetLatch(MyLatch);
-		rc = WaitLatch(MyLatch,
-					   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-					   3000,
-					   WAIT_EVENT_CHECKSUM_ENABLE_STARTCONDITION);
-
-		/*
-		 * If the postmaster died, bail out.  But first print a log message to
-		 * note that the checksumming didn't complete.
-		 */
-		if (rc & WL_POSTMASTER_DEATH)
-			ereport(FATAL,
-					errcode(ERRCODE_ADMIN_SHUTDOWN),
-					errmsg("postmaster exited during data checksums processing"),
-					errhint("Data checksums processing must be restarted manually after cluster restart."));
-
-		CHECK_FOR_INTERRUPTS();
-		CHECK_FOR_LAUNCHER_ABORT_REQUEST();
-
-		if (abort_requested)
-			break;
-	}
-
-	pgstat_report_activity(STATE_IDLE, NULL);
-	return;
-}
-
-/*
- * DataChecksumsWorkerLauncherMain
- *
- * Main function for launching dynamic background workers for processing data
- * checksums in databases. This function has the bgworker management, with
- * ProcessAllDatabases being responsible for looping over the databases and
- * initiating processing.
- */
-void
-DataChecksumsWorkerLauncherMain(Datum arg)
-{
-
-	ereport(DEBUG1,
-			errmsg("background worker \"datachecksums launcher\" started"));
-
-	pqsignal(SIGTERM, die);
-	pqsignal(SIGINT, launcher_cancel_handler);
-	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
-	pqsignal(SIGUSR2, PG_SIG_IGN);
-
-	BackgroundWorkerUnblockSignals();
-
-	MyBackendType = B_DATACHECKSUMSWORKER_LAUNCHER;
-	init_ps_display(NULL);
-
-	INJECTION_POINT("datachecksumsworker-launcher-delay", NULL);
-
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-
-	if (DataChecksumState->launcher_running)
-	{
-		ereport(LOG,
-				errmsg("background worker \"datachecksums launcher\" already running, exiting"));
-		/* Launcher was already running, let it finish */
-		LWLockRelease(DataChecksumsWorkerLock);
-		return;
-	}
-
-	on_shmem_exit(launcher_exit, 0);
-	launcher_running = true;
-
-	/* Initialize a connection to shared catalogs only */
-	BackgroundWorkerInitializeConnectionByOid(InvalidOid, InvalidOid, 0);
-
-	operation = DataChecksumState->launch_operation;
-	DataChecksumState->launcher_running = true;
-	DataChecksumState->operation = operation;
-	DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
-	DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	/*
-	 * The target state can change while we are busy enabling/disabling
-	 * checksums, if the user calls pg_disable/enable_data_checksums() before
-	 * we are finished with the previous request. In that case, we will loop
-	 * back here, to process the new request.
-	 */
-again:
-
-	pgstat_progress_start_command(PROGRESS_COMMAND_DATACHECKSUMS,
-								  InvalidOid);
-	ResetDataChecksumsProgressCounters();
-
-	if (operation == ENABLE_DATACHECKSUMS)
-	{
-		/*
-		 * If we are asked to enable checksums in a cluster which already has
-		 * checksums enabled, exit immediately as there is nothing more to do.
-		 */
-		if (DataChecksumsNeedVerify())
-			goto done;
-
-		ereport(LOG,
-				errmsg("enabling data checksums requested, starting data checksum calculation"));
-
-		/*
-		 * Set the state to inprogress-on and wait on the procsignal barrier.
-		 */
-		pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
-									 PROGRESS_DATACHECKSUMS_PHASE_ENABLING);
-		SetDataChecksumsOnInProgress();
-
-		/*
-		 * All backends are now in inprogress-on state and are writing data
-		 * checksums.  Start processing all data at rest.
-		 */
-		if (!ProcessAllDatabases())
-		{
-			/*
-			 * If processing was canceled, or the target state changed during
-			 * processing, then it's not a failure. In the latter case, the
-			 * launcher will restart processing with the new target state.
-			 */
-			CHECK_FOR_LAUNCHER_ABORT_REQUEST();
-			if (abort_requested)
-				goto done;
-			ereport(ERROR,
-					errcode(ERRCODE_INSUFFICIENT_RESOURCES),
-					errmsg("unable to enable data checksums in cluster"));
-		}
-
-		/*
-		 * Data checksums have been set on all pages, set the state to on in
-		 * order to instruct backends to validate checksums on reading.
-		 */
-		SetDataChecksumsOn();
-
-		ereport(LOG,
-				errmsg("data checksums are now enabled"));
-	}
-	else if (operation == DISABLE_DATACHECKSUMS)
-	{
-		ereport(LOG,
-				errmsg("disabling data checksums requested"));
-
-		pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
-									 PROGRESS_DATACHECKSUMS_PHASE_DISABLING);
-		SetDataChecksumsOff();
-		ereport(LOG,
-				errmsg("data checksums are now disabled"));
-	}
-	else
-		Assert(false);
-
-done:
-
-	/*
-	 * This state will only be displayed for a fleeting moment, but for the
-	 * sake of correctness it is still added before ending the command.
-	 */
-	pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
-								 PROGRESS_DATACHECKSUMS_PHASE_DONE);
-
-	/*
-	 * All done. But before we exit, check if the target state was changed
-	 * while we were running. In that case we will have to start all over
-	 * again.
-	 */
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	if (DataChecksumState->launch_operation != operation)
-	{
-		DataChecksumState->operation = DataChecksumState->launch_operation;
-		operation = DataChecksumState->launch_operation;
-		DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
-		DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
-		LWLockRelease(DataChecksumsWorkerLock);
-		goto again;
-	}
-
-	/* Shut down progress reporting as we are done */
-	pgstat_progress_end_command();
-
-	launcher_running = false;
-	DataChecksumState->launcher_running = false;
-	LWLockRelease(DataChecksumsWorkerLock);
-}
-
-/*
- * ProcessAllDatabases
- *		Compute the list of all databases and process checksums in each
- *
- * This will generate a list of databases to process for enabling checksums.
- * If a database encounters a failure then processing will end immediately and
- * return an error.
- */
-static bool
-ProcessAllDatabases(void)
-{
-	List	   *DatabaseList;
-	int			cumulative_total = 0;
-
-	/* Set up so first run processes shared catalogs, not once in every db */
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	DataChecksumState->process_shared_catalogs = true;
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	/* Get a list of all databases to process */
-	WaitForAllTransactionsToFinish();
-	if (abort_requested)
-		return false;
-	DatabaseList = BuildDatabaseList();
-
-	/*
-	 * Update progress reporting with the total number of databases we need to
-	 * process.  This number should not be changed during processing, the
-	 * columns for processed databases is instead increased such that it can
-	 * be compared against the total.
-	 */
-	{
-		const int	index[] = {
-			PROGRESS_DATACHECKSUMS_DBS_TOTAL,
-			PROGRESS_DATACHECKSUMS_DBS_DONE,
-		};
-
-		int64		vals[2];
-
-		vals[0] = list_length(DatabaseList);
-		vals[1] = 0;
-
-		pgstat_progress_update_multi_param(2, index, vals);
-	}
-
-	foreach_ptr(DataChecksumsWorkerDatabase, db, DatabaseList)
-	{
-		DataChecksumsWorkerResult result;
-
-		result = ProcessDatabase(db);
-
-#ifdef USE_INJECTION_POINTS
-		/* Allow a test process to alter the result of the operation */
-		if (IS_INJECTION_POINT_ATTACHED("datachecksumsworker-fail-db-result"))
-		{
-			result = DATACHECKSUMSWORKER_FAILED;
-			INJECTION_POINT_CACHED("datachecksumsworker-fail-db-result",
-								   db->dbname);
-		}
-#endif
-
-		pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_DBS_DONE,
-									 ++cumulative_total);
-
-		if (result == DATACHECKSUMSWORKER_FAILED)
-		{
-			/*
-			 * Disable checksums on cluster, because we failed one of the
-			 * databases and this is an all or nothing process.
-			 */
-			SetDataChecksumsOff();
-			ereport(ERROR,
-					errcode(ERRCODE_INSUFFICIENT_RESOURCES),
-					errmsg("data checksums failed to get enabled in all databases, aborting"),
-					errhint("The server log might have more information on the cause of the error."));
-		}
-		else if (result == DATACHECKSUMSWORKER_ABORTED || abort_requested)
-		{
-			/* Abort flag set, so exit the whole process */
-			FreeDatabaseList(DatabaseList);
-			return false;
-		}
-		else if (result == DATACHECKSUMSWORKER_DROPDB)
-		{
-			/*
-			 * Ignore databases that were dropped before their worker could
-			 * process them, and continue with the remaining databases.
-			 */
-			continue;
-		}
-
-		/*
-		 * When one database has completed, it will have done shared catalogs
-		 * so we don't have to process them again.
-		 */
-		LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-		DataChecksumState->process_shared_catalogs = false;
-		LWLockRelease(DataChecksumsWorkerLock);
-	}
-
-	FreeDatabaseList(DatabaseList);
-
-	pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
-								 PROGRESS_DATACHECKSUMS_PHASE_WAITING_BARRIER);
-	return true;
-}
-
-/*
- * DataChecksumsShmemRequest
- *		Request datachecksumsworker-related shared memory
- */
-static void
-DataChecksumsShmemRequest(void *arg)
-{
-	ShmemRequestStruct(.name = "DataChecksumsWorker Data",
-					   .size = sizeof(DataChecksumsStateStruct),
-					   .ptr = (void **) &DataChecksumState,
-		);
-}
-
-/*
- * DatabaseExists
- *
- * Scans the system catalog to check if a database with the given Oid exists
- * and returns true if it is found, even if it is marked invalid.  An invalid
- * database still has files that need checksums, so only a missing catalog row
- * proves that a concurrent DROP DATABASE completed.
- */
-static bool
-DatabaseExists(Oid dboid)
-{
-	Relation	rel;
-	ScanKeyData skey;
-	SysScanDesc scan;
-	bool		found;
-	HeapTuple	tuple;
-
-	StartTransactionCommand();
-
-	/*
-	 * DROP DATABASE holds an exclusive lock on the database from before it
-	 * terminates the connections to it until it commits, so take a lock which
-	 * conflicts with it to wait out a drop which is in flight.  Without this
-	 * we can see a database whose worker was just killed by DROP DATABASE ...
-	 * WITH (FORCE) as still existing, and report a spurious failure.
-	 */
-	LockSharedObject(DatabaseRelationId, dboid, 0, AccessShareLock);
-
-	rel = table_open(DatabaseRelationId, AccessShareLock);
-	ScanKeyInit(&skey,
-				Anum_pg_database_oid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(dboid));
-	scan = systable_beginscan(rel, DatabaseOidIndexId, true, SnapshotSelf,
-							  1, &skey);
-	tuple = systable_getnext(scan);
-	found = HeapTupleIsValid(tuple);
-
-	systable_endscan(scan);
-	table_close(rel, AccessShareLock);
-
-	CommitTransactionCommand();
-
-	return found;
-}
-
-/*
- * ErrorOnInvalidDatabases
- *		Error out if the cluster contains an invalid database
- *
- * A database left invalid by an interrupted DROP DATABASE cannot be connected
- * to, so data checksums can never be enabled in it, while its files remain on
- * disk where checksum verification will find them.  Report it to the caller
- * so the user can drop it before retrying.  Called from a normal backend, so
- * unlike DatabaseExists we are already in a transaction.
- *
- * A cluster can contain more than one invalid database, but only the first one
- * found is reported; collecting them all is not worth the complexity here.  A
- * user with several of them gets the error again for the next one after
- * dropping the reported database, which the hint accounts for.
- */
-static void
-ErrorOnInvalidDatabases(void)
-{
-	Relation	rel;
-	TableScanDesc scan;
-	HeapTuple	tup;
-
-	rel = table_open(DatabaseRelationId, AccessShareLock);
-	scan = table_beginscan_catalog(rel, 0, NULL);
-
-	while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
-	{
-		Form_pg_database pgdb = (Form_pg_database) GETSTRUCT(tup);
-
-		if (database_is_invalid_form(pgdb))
-			ereport(ERROR,
-					errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-					errmsg("cannot enable data checksums in a cluster with invalid database \"%s\"",
-						   NameStr(pgdb->datname)),
-					errhint("Use DROP DATABASE to drop invalid databases."));
-	}
-
-	table_endscan(scan);
-	table_close(rel, AccessShareLock);
-}
-
-/*
- * BuildDatabaseList
- *		Compile a list of all currently available databases in the cluster
- *
- * This creates the list of databases for the datachecksumsworker workers to
- * add checksums to. If the caller wants to ensure that no concurrently
- * running CREATE DATABASE calls exist, this needs to be preceded by a call
- * to WaitForAllTransactionsToFinish().
- */
-static List *
-BuildDatabaseList(void)
-{
-	List	   *DatabaseList = NIL;
-	Relation	rel;
-	TableScanDesc scan;
-	HeapTuple	tup;
-	MemoryContext ctx = CurrentMemoryContext;
-	MemoryContext oldctx;
-
-	StartTransactionCommand();
-
-	rel = table_open(DatabaseRelationId, AccessShareLock);
-	scan = table_beginscan_catalog(rel, 0, NULL);
-
-	while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
-	{
-		Form_pg_database pgdb = (Form_pg_database) GETSTRUCT(tup);
-		DataChecksumsWorkerDatabase *db;
-
-		oldctx = MemoryContextSwitchTo(ctx);
-
-		db = (DataChecksumsWorkerDatabase *) palloc0(sizeof(DataChecksumsWorkerDatabase));
-
-		db->dboid = pgdb->oid;
-		db->dbname = pstrdup(NameStr(pgdb->datname));
-
-		DatabaseList = lappend(DatabaseList, db);
-
-		MemoryContextSwitchTo(oldctx);
-	}
-
-	table_endscan(scan);
-	table_close(rel, AccessShareLock);
-
-	CommitTransactionCommand();
-
-	return DatabaseList;
-}
-
-static void
-FreeDatabaseList(List *dblist)
-{
-	if (!dblist)
-		return;
-
-	foreach_ptr(DataChecksumsWorkerDatabase, db, dblist)
-	{
-		if (db->dbname != NULL)
-			pfree(db->dbname);
-	}
-
-	list_free_deep(dblist);
-}
-
-/*
- * BuildRelationList
- *		Compile a list of relations in the database
- *
- * Returns a list of OIDs for the requested relation types. If temp_relations
- * is True then only temporary relations with storage are returned.  If
- * temp_relations is False then non-temporary relations with storage are
- * returned.  If include_shared is True then shared relations are included as
- * well in a non-temporary list. include_shared has no relevance when building
- * a list of temporary relations.
- */
-static List *
-BuildRelationList(bool temp_relations, bool include_shared)
-{
-	List	   *RelationList = NIL;
-	Relation	rel;
-	TableScanDesc scan;
-	HeapTuple	tup;
-	MemoryContext ctx = CurrentMemoryContext;
-	MemoryContext oldctx;
-
-	StartTransactionCommand();
-
-	rel = table_open(RelationRelationId, AccessShareLock);
-	scan = table_beginscan_catalog(rel, 0, NULL);
-
-	while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
-	{
-		Form_pg_class pgc = (Form_pg_class) GETSTRUCT(tup);
-
-		if (!RELKIND_HAS_STORAGE(pgc->relkind))
-			continue;
-
-		/* Only include temporary relations when explicitly asked to */
-		if (pgc->relpersistence == RELPERSISTENCE_TEMP)
-		{
-			if (!temp_relations)
-				continue;
-		}
-		else
-		{
-			/*
-			 * If we are only interested in temp relations then continue
-			 * immediately as the current relation isn't a temp relation.
-			 */
-			if (temp_relations)
-				continue;
-
-			if (pgc->relisshared && !include_shared)
-				continue;
-		}
-
-		oldctx = MemoryContextSwitchTo(ctx);
-		RelationList = lappend_oid(RelationList, pgc->oid);
-		MemoryContextSwitchTo(oldctx);
-	}
-
-	table_endscan(scan);
-	table_close(rel, AccessShareLock);
-
-	CommitTransactionCommand();
-
-	return RelationList;
-}
-
-/*
- * DataChecksumsWorkerMain
- *
- * Main function for enabling checksums in a single database. This is the
- * function set as the bgw_function_name in the dynamic background worker
- * process initiated for each database by the worker launcher. After enabling
- * data checksums in each applicable relation in the database, it will wait for
- * all temporary relations that were present when the function started to
- * disappear before returning. This is required since we cannot rewrite
- * existing temporary relations with data checksums.
- */
-void
-DataChecksumsWorkerMain(Datum arg)
-{
-	Oid			dboid;
-	List	   *RelationList = NIL;
-	List	   *InitialTempTableList = NIL;
-	BufferAccessStrategy strategy;
-	bool		aborted = false;
-	int64		rels_done;
-	bool		process_shared;
-#ifdef USE_INJECTION_POINTS
-	bool		retried = false;
-#endif
-
-	worker_invocation = DatumGetUInt64(arg);
-
-	operation = ENABLE_DATACHECKSUMS;
-
-	pqsignal(SIGTERM, die);
-	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
-
-	BackgroundWorkerUnblockSignals();
-
-	MyBackendType = B_DATACHECKSUMSWORKER_WORKER;
-	init_ps_display(NULL);
-
-	LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);
-	if (DataChecksumState->worker_invocation != worker_invocation)
-	{
-		LWLockRelease(DataChecksumsWorkerLock);
-		return;
-	}
-	dboid = DataChecksumState->database_oid;
-	LWLockRelease(DataChecksumsWorkerLock);
-
-	BackgroundWorkerInitializeConnectionByOid(dboid, InvalidOid,
-											  BGWORKER_BYPASS_ALLOWCONN);
-
-	/* worker will have a separate entry in pg_stat_progress_data_checksums */
-	pgstat_progress_start_command(PROGRESS_COMMAND_DATACHECKSUMS,
-								  InvalidOid);
-	ResetDataChecksumsProgressCounters();
-
-	/*
-	 * Get a list of all temp tables present as we start in this database. We
-	 * need to wait until they are all gone before we exit.  For the list of
-	 * relations to enable checksums in, check if shared catalogs have been
-	 * processed already.
-	 */
-	InitialTempTableList = BuildRelationList(true, false);
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	if (DataChecksumState->worker_invocation != worker_invocation)
-	{
-		LWLockRelease(DataChecksumsWorkerLock);
-		return;
-	}
-	process_shared = DataChecksumState->process_shared_catalogs;
-
-	/*
-	 * Enable vacuum cost delay, if any.  While this process isn't doing any
-	 * vacuuming, we are re-using the infrastructure that vacuum cost delay
-	 * provides rather than inventing something bespoke. This is an internal
-	 * implementation detail and care should be taken to avoid it bleeding
-	 * through to the user to avoid confusion.
-	 *
-	 * VacuumUpdateCosts() propagates the values to the variables actually
-	 * read by vacuum_delay_point().
-	 */
-	VacuumCostDelay = DataChecksumState->cost_delay;
-	VacuumCostLimit = DataChecksumState->cost_limit;
-	LWLockRelease(DataChecksumsWorkerLock);
-	VacuumUpdateCosts();
-	VacuumCostBalance = 0;
-
-	/*
-	 * Create and set the vacuum strategy as our buffer strategy.
-	 */
-	strategy = GetAccessStrategy(BAS_VACUUM);
-
-	RelationList = BuildRelationList(false, process_shared);
-
-	/* Update the total number of relations to be processed in this DB. */
-	{
-		const int	index[] = {
-			PROGRESS_DATACHECKSUMS_RELS_TOTAL,
-			PROGRESS_DATACHECKSUMS_RELS_DONE
-		};
-
-		int64		vals[2];
-
-		vals[0] = list_length(RelationList);
-		vals[1] = 0;
-
-		pgstat_progress_update_multi_param(2, index, vals);
-	}
-
-	/* Process the relations */
-	rels_done = 0;
-	foreach_oid(reloid, RelationList)
-	{
-		bool		costs_updated = false;
-
-		if (!ProcessSingleRelationByOid(reloid, strategy))
-		{
-			aborted = true;
-			break;
-		}
-
-		pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_RELS_DONE,
-									 ++rels_done);
-		CHECK_FOR_INTERRUPTS();
-		CHECK_FOR_WORKER_ABORT_REQUEST();
-
-		if (abort_requested)
-			break;
-
-		/*
-		 * Check if the cost settings changed during runtime and if so, update
-		 * to reflect the new values and signal that the access strategy needs
-		 * to be refreshed.
-		 */
-		LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-		if (DataChecksumState->worker_invocation != worker_invocation)
-		{
-			LWLockRelease(DataChecksumsWorkerLock);
-			break;
-		}
-		if ((DataChecksumState->launch_cost_delay != DataChecksumState->cost_delay)
-			|| (DataChecksumState->launch_cost_limit != DataChecksumState->cost_limit))
-		{
-			costs_updated = true;
-			VacuumCostDelay = DataChecksumState->launch_cost_delay;
-			VacuumCostLimit = DataChecksumState->launch_cost_limit;
-			VacuumUpdateCosts();
-
-			DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
-			DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
-		}
-		else
-			costs_updated = false;
-		LWLockRelease(DataChecksumsWorkerLock);
-
-		if (costs_updated)
-		{
-			FreeAccessStrategy(strategy);
-			strategy = GetAccessStrategy(BAS_VACUUM);
-		}
-	}
-
-	list_free(RelationList);
-	FreeAccessStrategy(strategy);
-
-	if (aborted || abort_requested)
-	{
-		LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-		if (DataChecksumState->worker_invocation == worker_invocation)
-			DataChecksumState->worker_result = DATACHECKSUMSWORKER_ABORTED;
-		LWLockRelease(DataChecksumsWorkerLock);
-		ereport(DEBUG1,
-				errmsg("data checksum processing aborted in database OID %u",
-					   dboid));
-		return;
-	}
-
-	/* The worker is about to wait for temporary tables to go away. */
-	pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
-								 PROGRESS_DATACHECKSUMS_PHASE_WAITING_TEMPREL);
-
-	/*
-	 * Wait for all temp tables that existed when we started to go away. This
-	 * is necessary since we cannot "reach" them to enable checksums. Any temp
-	 * tables created after we started will already have checksums in them
-	 * (due to the "inprogress-on" state), so no need to wait for those.
-	 */
-	for (;;)
-	{
-		List	   *CurrentTempTables;
-		int			numleft;
-		char		activity[64];
-
-		CurrentTempTables = BuildRelationList(true, false);
-		numleft = 0;
-		foreach_oid(tmptbloid, InitialTempTableList)
-		{
-			if (list_member_oid(CurrentTempTables, tmptbloid))
-				numleft++;
-		}
-		list_free(CurrentTempTables);
-
-#ifdef USE_INJECTION_POINTS
-		if (IS_INJECTION_POINT_ATTACHED("datachecksumsworker-fake-temptable-wait"))
-		{
-			/* Make sure to just cause one retry */
-			if (!retried && numleft == 0)
-			{
-				numleft = 1;
-				retried = true;
-
-				INJECTION_POINT_CACHED("datachecksumsworker-fake-temptable-wait", NULL);
-			}
-		}
-#endif
-
-		if (numleft == 0)
-			break;
-
-		/*
-		 * At least one temp table is left to wait for, indicate in pgstat
-		 * activity and progress reporting.
-		 */
-		snprintf(activity,
-				 sizeof(activity),
-				 "Waiting for %d temp tables to be removed", numleft);
-		pgstat_report_activity(STATE_RUNNING, activity);
-
-		/* Retry every 3 seconds */
-		ResetLatch(MyLatch);
-		(void) WaitLatch(MyLatch,
-						 WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
-						 3000,
-						 WAIT_EVENT_CHECKSUM_ENABLE_TEMPTABLE_WAIT);
-
-		CHECK_FOR_INTERRUPTS();
-		CHECK_FOR_WORKER_ABORT_REQUEST();
-
-		if (aborted || abort_requested)
-		{
-			LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-			if (DataChecksumState->worker_invocation == worker_invocation)
-				DataChecksumState->worker_result = DATACHECKSUMSWORKER_ABORTED;
-			LWLockRelease(DataChecksumsWorkerLock);
-			ereport(LOG,
-					errmsg("data checksum processing aborted in database OID %u",
-						   dboid));
-			return;
-		}
-	}
-
-	list_free(InitialTempTableList);
-
-	/* worker done */
-	pgstat_progress_end_command();
-
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	if (DataChecksumState->worker_invocation == worker_invocation)
-		DataChecksumState->worker_result = DATACHECKSUMSWORKER_SUCCESSFUL;
-	LWLockRelease(DataChecksumsWorkerLock);
-}
diff --git a/src/backend/postmaster/meson.build b/src/backend/postmaster/meson.build
index 6cba23bbeef..e1f70726604 100644
--- a/src/backend/postmaster/meson.build
+++ b/src/backend/postmaster/meson.build
@@ -6,7 +6,6 @@ backend_sources += files(
   'bgworker.c',
   'bgwriter.c',
   'checkpointer.c',
-  'datachecksum_state.c',
   'fork_process.c',
   'interrupt.c',
   'launch_backend.c',
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index c5b141ed3e3..2ba40fde67b 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3024,11 +3024,6 @@ PostmasterStateMachine(void)
 									B_INVALID,
 									B_STANDALONE_BACKEND);
 
-			/* also add data checksums processes */
-			remainMask = btmask_add(remainMask,
-									B_DATACHECKSUMSWORKER_LAUNCHER,
-									B_DATACHECKSUMSWORKER_WORKER);
-
 			/* All types should be included in targetMask or remainMask */
 			Assert((remainMask.mask | targetMask.mask) == BTYPE_MASK_ALL.mask);
 		}
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index c944be4ac83..570b0e9d285 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -190,22 +190,6 @@ xlog_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 	}
 }
 
-void
-xlog2_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
-{
-	uint8		info = XLogRecGetInfo(buf->record) & ~XLR_INFO_MASK;
-
-	ReorderBufferProcessXid(ctx->reorder, XLogRecGetXid(buf->record), buf->origptr);
-
-	switch (info)
-	{
-		case XLOG2_CHECKSUMS:
-			break;
-		default:
-			elog(ERROR, "unexpected RM_XLOG2_ID record type: %u", info);
-	}
-}
-
 /*
  * Handle rmgr XACT_ID records for LogicalDecodingProcessRecord().
  */
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
index 1397f65f67b..f8091d83099 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -23,7 +23,6 @@
 #include "miscadmin.h"
 #include "pgstat.h"
 #include "port/pg_bitutils.h"
-#include "postmaster/datachecksum_state.h"
 #include "replication/logicalctl.h"
 #include "replication/logicalworker.h"
 #include "replication/slotsync.h"
@@ -591,13 +590,6 @@ ProcessProcSignalBarrier(void)
 					case PROCSIGNAL_BARRIER_UPDATE_XLOG_LOGICAL_INFO:
 						processed = ProcessBarrierUpdateXLogLogicalInfo();
 						break;
-
-					case PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON:
-					case PROCSIGNAL_BARRIER_CHECKSUM_ON:
-					case PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF:
-					case PROCSIGNAL_BARRIER_CHECKSUM_OFF:
-						processed = AbsorbDataChecksumsBarrier(type);
-						break;
 				}
 
 				/*
diff --git a/src/backend/storage/page/README b/src/backend/storage/page/README
index 73c36a63908..e30d7ac59ad 100644
--- a/src/backend/storage/page/README
+++ b/src/backend/storage/page/README
@@ -10,9 +10,7 @@ http://www.cs.toronto.edu/~bianca/papers/sigmetrics09.pdf, discussed
 2010/12/22 on -hackers list.
 
 Current implementation requires this be enabled system-wide at initdb time, or
-by using the pg_checksums tool on an offline cluster.  Checksums can also be
-enabled at runtime using pg_enable_data_checksums(), and disabled by using
-pg_disable_data_checksums().
+by using the pg_checksums tool on an offline cluster.
 
 The checksum is not valid at all times on a data page!!
 The checksum is valid when the page leaves the shared pool and is checked
diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c
index 8df74618fcd..3b429048436 100644
--- a/src/backend/storage/page/bufpage.c
+++ b/src/backend/storage/page/bufpage.c
@@ -107,15 +107,7 @@ PageIsVerified(PageData *page, BlockNumber blkno, int flags, bool *checksum_fail
 	 */
 	if (!PageIsNew(page))
 	{
-		/*
-		 * There shouldn't be any check for interrupt calls happening in this
-		 * codepath, but just to be on the safe side we hold interrupts since
-		 * if they did happen the data checksum state could change during
-		 * verifying checksums, which could lead to incorrect verification
-		 * results.
-		 */
-		HOLD_INTERRUPTS();
-		if (DataChecksumsNeedVerify())
+		if (DataChecksumsEnabled())
 		{
 			checksum = pg_checksum_page(page, blkno);
 
@@ -126,7 +118,6 @@ PageIsVerified(PageData *page, BlockNumber blkno, int flags, bool *checksum_fail
 					*checksum_failure_p = true;
 			}
 		}
-		RESUME_INTERRUPTS();
 
 		/*
 		 * The following checks don't prove the header is correct, only that
@@ -1519,14 +1510,9 @@ PageIndexTupleOverwrite(Page page, OffsetNumber offnum,
 void
 PageSetChecksum(Page page, BlockNumber blkno)
 {
-	HOLD_INTERRUPTS();
 	/* If we don't need a checksum, just return */
-	if (PageIsNew(page) || !DataChecksumsNeedWrite())
-	{
-		RESUME_INTERRUPTS();
+	if (PageIsNew(page) || !DataChecksumsEnabled())
 		return;
-	}
 
 	((PageHeader) page)->pd_checksum = pg_checksum_page(page, blkno);
-	RESUME_INTERRUPTS();
 }
diff --git a/src/backend/utils/activity/pgstat_backend.c b/src/backend/utils/activity/pgstat_backend.c
index 73461c9bca5..c5fecbf577c 100644
--- a/src/backend/utils/activity/pgstat_backend.c
+++ b/src/backend/utils/activity/pgstat_backend.c
@@ -381,8 +381,6 @@ pgstat_tracks_backend_bktype(BackendType bktype)
 		case B_CHECKPOINTER:
 		case B_IO_WORKER:
 		case B_STARTUP:
-		case B_DATACHECKSUMSWORKER_LAUNCHER:
-		case B_DATACHECKSUMSWORKER_WORKER:
 			return false;
 
 		case B_AUTOVAC_WORKER:
diff --git a/src/backend/utils/activity/pgstat_io.c b/src/backend/utils/activity/pgstat_io.c
index 8ec1aad5078..ae52baafd11 100644
--- a/src/backend/utils/activity/pgstat_io.c
+++ b/src/backend/utils/activity/pgstat_io.c
@@ -354,8 +354,6 @@ pgstat_tracks_io_bktype(BackendType bktype)
 		case B_LOGGER:
 			return false;
 
-		case B_DATACHECKSUMSWORKER_LAUNCHER:
-		case B_DATACHECKSUMSWORKER_WORKER:
 		case B_AUTOVAC_LAUNCHER:
 		case B_AUTOVAC_WORKER:
 		case B_BACKEND:
@@ -456,37 +454,6 @@ pgstat_tracks_io_object(BackendType bktype, IOObject io_object,
 		io_context == IOCONTEXT_BULKWRITE)
 		return false;
 
-	/*
-	 * The data checksums launcher scans catalogs and emits WAL records for
-	 * checksum state changes. Catalog scans can use a bulkread strategy.
-	 */
-	if (bktype == B_DATACHECKSUMSWORKER_LAUNCHER)
-	{
-		if (io_object == IOOBJECT_WAL ||
-			(io_object == IOOBJECT_RELATION &&
-			 (io_context == IOCONTEXT_BULKREAD ||
-			  io_context == IOCONTEXT_NORMAL)))
-			return true;
-
-		return false;
-	}
-
-	/*
-	 * The worker also scans catalogs, then processes relations using a vacuum
-	 * access strategy. Catalog scans can use a bulkread strategy.
-	 */
-	if (bktype == B_DATACHECKSUMSWORKER_WORKER)
-	{
-		if (io_object == IOOBJECT_WAL ||
-			(io_object == IOOBJECT_RELATION &&
-			 (io_context == IOCONTEXT_BULKREAD ||
-			  io_context == IOCONTEXT_NORMAL ||
-			  io_context == IOCONTEXT_VACUUM)))
-			return true;
-
-		return false;
-	}
-
 	return true;
 }
 
@@ -530,8 +497,6 @@ pgstat_tracks_io_op(BackendType bktype, IOObject io_object,
 	if (io_object == IOOBJECT_WAL && io_op == IOOP_READ &&
 		(bktype == B_WAL_RECEIVER || bktype == B_BG_WRITER ||
 		 bktype == B_AUTOVAC_LAUNCHER || bktype == B_AUTOVAC_WORKER ||
-		 bktype == B_DATACHECKSUMSWORKER_LAUNCHER ||
-		 bktype == B_DATACHECKSUMSWORKER_WORKER ||
 		 bktype == B_WAL_WRITER))
 		return false;
 
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 256b3a3c02e..78e994dc0c5 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -116,8 +116,6 @@ CHECKPOINT_DELAY_COMPLETE	"Waiting for a backend that blocks a checkpoint from c
 CHECKPOINT_DELAY_START	"Waiting for a backend that blocks a checkpoint from starting."
 CHECKPOINT_DONE	"Waiting for a checkpoint to complete."
 CHECKPOINT_START	"Waiting for a checkpoint to start."
-CHECKSUM_ENABLE_STARTCONDITION	"Waiting for data checksums enabling to start."
-CHECKSUM_ENABLE_TEMPTABLE_WAIT	"Waiting for temporary tables to be dropped for data checksums to be enabled."
 EXECUTE_GATHER	"Waiting for activity from a child process while executing a <literal>Gather</literal> plan node."
 HASH_BATCH_ALLOCATE	"Waiting for an elected Parallel Hash participant to allocate a hash table."
 HASH_BATCH_ELECT	"Waiting to elect a Parallel Hash participant to allocate a hash table."
@@ -369,7 +367,6 @@ SerialControl	"Waiting to read or update shared <filename>pg_serial</filename> s
 AioWorkerSubmissionQueue	"Waiting to access AIO worker submission queue."
 WaitLSN	"Waiting to read or update shared Wait-for-LSN state."
 LogicalDecodingControl	"Waiting to read or update logical decoding status information."
-DataChecksumsWorker	"Waiting for data checksums worker."
 AioWorkerControl	"Waiting to update AIO worker information."
 
 #
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 0c59df17901..fce3b4f4088 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -297,8 +297,6 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 		cmdtype = PROGRESS_COMMAND_BASEBACKUP;
 	else if (pg_strcasecmp(cmd, "COPY") == 0)
 		cmdtype = PROGRESS_COMMAND_COPY;
-	else if (pg_strcasecmp(cmd, "DATACHECKSUMS") == 0)
-		cmdtype = PROGRESS_COMMAND_DATACHECKSUMS;
 	else
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1184,6 +1182,9 @@ pg_stat_get_db_checksum_failures(PG_FUNCTION_ARGS)
 	int64		result;
 	PgStat_StatDBEntry *dbentry;
 
+	if (!DataChecksumsEnabled())
+		PG_RETURN_NULL();
+
 	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
 		result = 0;
 	else
@@ -1199,6 +1200,9 @@ pg_stat_get_db_checksum_last_failure(PG_FUNCTION_ARGS)
 	TimestampTz result;
 	PgStat_StatDBEntry *dbentry;
 
+	if (!DataChecksumsEnabled())
+		PG_RETURN_NULL();
+
 	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
 		result = 0;
 	else
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 7ffc808073a..ba191977697 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -845,8 +845,7 @@ InitializeSessionUserIdStandalone(void)
 	 * workers, in slot sync worker and in background workers.
 	 */
 	Assert(!IsUnderPostmaster || AmAutoVacuumWorkerProcess() ||
-		   AmLogicalSlotSyncWorkerProcess() || AmBackgroundWorkerProcess() ||
-		   AmDataChecksumsWorkerProcess());
+		   AmLogicalSlotSyncWorkerProcess() || AmBackgroundWorkerProcess());
 
 	/* call only once */
 	Assert(!OidIsValid(AuthenticatedUserId));
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 3d8c9bdebd5..ebbcfc62a4d 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -759,36 +759,8 @@ InitPostgres(const char *in_dbname, Oid dboid,
 	 */
 	SharedInvalBackendInit(false);
 
-	/*
-	 * Prevent consuming interrupts between setting ProcSignalInit and setting
-	 * the initial local data checksum value.  If a barrier is emitted, and
-	 * absorbed, before local cached state is initialized the state transition
-	 * can be invalid.
-	 */
-	HOLD_INTERRUPTS();
-
 	ProcSignalInit(MyCancelKey, MyCancelKeyLength);
 
-	/*
-	 * Initialize a local cache of the data_checksum_version, to be updated by
-	 * the procsignal-based barriers.
-	 *
-	 * This intentionally happens after initializing the procsignal, otherwise
-	 * we might miss a state change. This means we can get a barrier for the
-	 * state we've just initialized.
-	 *
-	 * The postmaster (which is what gets forked into the new child process)
-	 * does not handle barriers, therefore it may not have the current value
-	 * of LocalDataChecksumState value (it'll have the value read from the
-	 * control file, which may be arbitrarily old).
-	 *
-	 * NB: Even if the postmaster handled barriers, the value might still be
-	 * stale, as it might have changed after this process forked.
-	 */
-	InitLocalDataChecksumState();
-
-	RESUME_INTERRUPTS();
-
 	/*
 	 * Also set up timeout handlers needed for backend operation.  We need
 	 * these in every case except bootstrap.
@@ -927,7 +899,7 @@ InitPostgres(const char *in_dbname, Oid dboid,
 					 errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
 							 username != NULL ? username : "postgres")));
 	}
-	else if (AmBackgroundWorkerProcess() || AmDataChecksumsWorkerProcess())
+	else if (AmBackgroundWorkerProcess())
 	{
 		if (username == NULL && !OidIsValid(useroid))
 		{
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index 15f9261dab6..635c3e00f0f 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -578,13 +578,11 @@
   max => '1.0',
 },
 
-{ name => 'data_checksums', type => 'enum', context => 'PGC_INTERNAL', group => 'PRESET_OPTIONS',
+{ name => 'data_checksums', type => 'bool', context => 'PGC_INTERNAL', group => 'PRESET_OPTIONS',
   short_desc => 'Shows whether data checksums are turned on for this cluster.',
   flags => 'GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED',
   variable => 'data_checksums',
-  boot_val => 'PG_DATA_CHECKSUM_OFF',
-  options => 'data_checksums_options',
-  show_hook => 'show_data_checksums',
+  boot_val => 'false',
 },
 
 # Can't be set by ALTER SYSTEM as it can lead to recursive definition
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 031dd60771e..463ca1967fd 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -512,14 +512,6 @@ static const struct config_enum_entry file_extend_method_options[] = {
 	{NULL, 0, false}
 };
 
-static const struct config_enum_entry data_checksums_options[] = {
-	{"on", PG_DATA_CHECKSUM_VERSION, true},
-	{"off", PG_DATA_CHECKSUM_OFF, true},
-	{"inprogress-on", PG_DATA_CHECKSUM_INPROGRESS_ON, true},
-	{"inprogress-off", PG_DATA_CHECKSUM_INPROGRESS_OFF, true},
-	{NULL, 0, false}
-};
-
 /*
  * Options for enum values stored in other modules
  */
@@ -648,6 +640,7 @@ static int	shared_memory_size_in_huge_pages;
 static int	wal_block_size;
 static int	num_os_semaphores;
 static int	effective_wal_level = WAL_LEVEL_REPLICA;
+static bool data_checksums;
 static bool integer_datetimes;
 
 #ifdef USE_ASSERT_CHECKING
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index 9014f0953e9..82ac9fc4537 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -69,8 +69,8 @@ pg_control_system(PG_FUNCTION_ARGS)
 Datum
 pg_control_checkpoint(PG_FUNCTION_ARGS)
 {
-	Datum		values[20];
-	bool		nulls[20];
+	Datum		values[19];
+	bool		nulls[19];
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
 	ControlFileData *ControlFile;
@@ -154,12 +154,9 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
 	values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
 	nulls[17] = false;
 
-	values[18] = Int32GetDatum(ControlFile->checkPointCopy.dataChecksumState);
+	values[18] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
 	nulls[18] = false;
 
-	values[19] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
-	nulls[19] = false;
-
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
 	PG_RETURN_DATUM(HeapTupleGetDatum(htup));
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 5538ad558c7..5218395f98a 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -557,11 +557,11 @@
                                         # archiver              autovacuum
                                         # backend               bgworker
                                         # bgwriter              checkpointer
-                                        # checksums             ioworker
-                                        # postmaster            slotsyncworker
-                                        # startup               syslogger
-                                        # walreceiver           walsummarizer
-                                        # walwriter             walsender
+                                        # ioworker              postmaster
+                                        # slotsyncworker        startup
+                                        # syslogger             walreceiver
+                                        # walsummarizer         walwriter
+                                        # walsender
                                         #
                                         # Level values in order of decreasing
                                         # detail:
diff --git a/src/bin/pg_checksums/t/002_actions.pl b/src/bin/pg_checksums/t/002_actions.pl
index 94a11a534e9..dc91e70acf0 100644
--- a/src/bin/pg_checksums/t/002_actions.pl
+++ b/src/bin/pg_checksums/t/002_actions.pl
@@ -216,6 +216,11 @@ $node->start;
 command_fails([ 'pg_checksums', '--check', '--pgdata' => $pgdata ],
 	"fails with online cluster");
 
+# Make sure pg_control_init reports the initial state as disabled
+my $result = $node->safe_psql('postgres',
+	'SELECT data_page_checksum_version FROM pg_control_init();');
+is($result, '0', 'ensure pg_control_init reports disabled state');
+
 # Check corruption of table on default tablespace.
 check_relation_corruption($node, 'corrupt1', 'pg_default');
 
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 6fc87ed114d..bd709a5c1d9 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -289,8 +289,6 @@ main(int argc, char *argv[])
 		   ControlFile->checkPointCopy.oldestCommitTsXid);
 	printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
 		   ControlFile->checkPointCopy.newestCommitTsXid);
-	printf(_("Latest checkpoint's data_checksum_version:%u\n"),
-		   ControlFile->checkPointCopy.dataChecksumState);
 	printf(_("Time of latest checkpoint:            %s\n"),
 		   ckpttime_str);
 	printf(_("Fake LSN counter for unlogged rels:   %X/%08X\n"),
diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c
index 8c69329805b..6abc2c0096a 100644
--- a/src/bin/pg_upgrade/controldata.c
+++ b/src/bin/pg_upgrade/controldata.c
@@ -15,7 +15,6 @@
 #include "access/xlog_internal.h"
 #include "common/string.h"
 #include "pg_upgrade.h"
-#include "storage/checksum.h"
 
 
 /*
@@ -737,14 +736,6 @@ check_control_data(ControlData *oldctrl,
 	 * check_for_isn_and_int8_passing_mismatch().
 	 */
 
-	/*
-	 * If data checksums are in any in-progress state then disallow the
-	 * upgrade. The user should either let the process finish, or turn off
-	 * data checksums, before retrying.
-	 */
-	if (oldctrl->data_checksum_version > PG_DATA_CHECKSUM_VERSION)
-		pg_fatal("data checksums are being enabled in the old cluster");
-
 	/*
 	 * We might eventually allow upgrades from checksum to no-checksum
 	 * clusters.
diff --git a/src/bin/pg_waldump/t/001_basic.pl b/src/bin/pg_waldump/t/001_basic.pl
index 53b2f016b80..c9d72326f0f 100644
--- a/src/bin/pg_waldump/t/001_basic.pl
+++ b/src/bin/pg_waldump/t/001_basic.pl
@@ -79,8 +79,7 @@ BRIN
 CommitTs
 ReplicationOrigin
 Generic
-LogicalMessage
-XLOG2$/,
+LogicalMessage$/,
 	'rmgr list');
 
 
diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h
index ae32ef16d67..3352b5f8532 100644
--- a/src/include/access/rmgrlist.h
+++ b/src/include/access/rmgrlist.h
@@ -47,4 +47,3 @@ PG_RMGR(RM_COMMIT_TS_ID, "CommitTs", commit_ts_redo, commit_ts_desc, commit_ts_i
 PG_RMGR(RM_REPLORIGIN_ID, "ReplicationOrigin", replorigin_redo, replorigin_desc, replorigin_identify, NULL, NULL, NULL, NULL)
 PG_RMGR(RM_GENERIC_ID, "Generic", generic_redo, generic_desc, generic_identify, NULL, NULL, generic_mask, NULL)
 PG_RMGR(RM_LOGICALMSG_ID, "LogicalMessage", logicalmsg_redo, logicalmsg_desc, logicalmsg_identify, NULL, NULL, NULL, logicalmsg_decode)
-PG_RMGR(RM_XLOG2_ID, "XLOG2", xlog2_redo, xlog2_desc, xlog2_identify, NULL, NULL, NULL, xlog2_decode)
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 130ba929109..d81ede22224 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -57,7 +57,6 @@ extern PGDLLIMPORT int CommitDelay;
 extern PGDLLIMPORT int CommitSiblings;
 extern PGDLLIMPORT bool track_wal_io_timing;
 extern PGDLLIMPORT int wal_decode_buffer_size;
-extern PGDLLIMPORT int data_checksums;
 
 extern PGDLLIMPORT int CheckPointSegments;
 
@@ -133,7 +132,7 @@ extern PGDLLIMPORT bool XLogLogicalInfo;
  * of the bits make it to disk, but the checksum wouldn't match.  Also WAL-log
  * them if forced by wal_log_hints=on.
  */
-#define XLogHintBitIsNeeded() (wal_log_hints || DataChecksumsNeedWrite())
+#define XLogHintBitIsNeeded() (wal_log_hints || DataChecksumsEnabled())
 
 /* Do we need to WAL-log information required only for Hot Standby and logical replication? */
 #define XLogStandbyInfoActive() (wal_level >= WAL_LEVEL_REPLICA)
@@ -243,11 +242,8 @@ extern void XLogSetReplicationSlotMinimumLSN(XLogRecPtr lsn);
 extern XLogRecPtr XLogGetReplicationSlotMinimumLSN(void);
 
 extern void xlog_redo(struct XLogReaderState *record);
-extern void xlog2_redo(struct XLogReaderState *record);
 extern void xlog_desc(StringInfo buf, struct XLogReaderState *record);
-extern void xlog2_desc(StringInfo buf, struct XLogReaderState *record);
 extern const char *xlog_identify(uint8 info);
-extern const char *xlog2_identify(uint8 info);
 
 extern void issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli);
 
@@ -260,19 +256,7 @@ extern XLogRecPtr GetXLogWriteRecPtr(void);
 
 extern uint64 GetSystemIdentifier(void);
 extern char *GetMockAuthenticationNonce(void);
-extern bool DataChecksumsNeedWrite(void);
-extern bool DataChecksumsNeedVerify(void);
-extern XLogRecPtr GetLastChecksumChangeRecPtr(void);
-extern bool DataChecksumsOn(void);
-extern bool DataChecksumsOff(void);
-extern bool DataChecksumsInProgressOn(void);
-extern void SetDataChecksumsOnInProgress(void);
-extern void SetDataChecksumsOn(void);
-extern void SetDataChecksumsOff(void);
-extern const char *show_data_checksums(void);
-extern const char *get_checksum_state_string(uint32 state);
-extern void InitLocalDataChecksumState(void);
-extern void SetLocalDataChecksumState(uint32 data_checksum_version);
+extern bool DataChecksumsEnabled(void);
 extern bool GetDefaultCharSignedness(void);
 extern XLogRecPtr GetFakeLSNForUnloggedRel(void);
 extern void BootStrapXLOG(uint32 data_checksum_version);
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index be718993401..3a2fd9d160e 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -288,12 +288,6 @@ typedef struct xl_restore_point
 	char		rp_name[MAXFNAMELEN];
 } xl_restore_point;
 
-/* Information logged when data checksum level is changed */
-typedef struct xl_checksum_state
-{
-	ChecksumStateType new_checksum_state;
-} xl_checksum_state;
-
 /* Overwrite of prior contrecord */
 typedef struct xl_overwrite_contrecord
 {
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 7b5404460ec..b875c5c0e3a 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -63,9 +63,6 @@ typedef struct CheckPoint
 	 * set to InvalidTransactionId.
 	 */
 	TransactionId oldestActiveXid;
-
-	/* data checksums state at the time of the checkpoint  */
-	uint32		dataChecksumState;
 } CheckPoint;
 
 /* XLOG info values for XLOG rmgr */
@@ -86,10 +83,6 @@ typedef struct CheckPoint
 #define XLOG_CHECKPOINT_REDO			0xE0
 #define XLOG_LOGICAL_DECODING_STATUS_CHANGE	0xF0
 
-/* XLOG info values for XLOG2 rmgr */
-#define XLOG2_CHECKSUMS					0x00
-
-
 /*
  * System status indicator.  Note this is stored in pg_control; if you change
  * it, you must bump PG_CONTROL_VERSION
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 805a579080d..81b13a4847a 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12384,18 +12384,6 @@
   proname => 'jsonb_subscript_handler', prorettype => 'internal',
   proargtypes => 'internal', prosrc => 'jsonb_subscript_handler' },
 
-# data checksum management functions
-{ oid => '6507', descr => 'disable data checksums',
-  proname => 'pg_disable_data_checksums', provolatile => 'v',
-  proparallel => 'r', prorettype => 'void', proargtypes => '',
-  prosrc => 'disable_data_checksums', proacl => '{POSTGRES=X}' },
-{ oid => '6506', descr => 'enable data checksums',
-  proname => 'pg_enable_data_checksums', provolatile => 'v', proparallel => 'r',
-  prorettype => 'void', proargtypes => 'int4 int4',
-  proallargtypes => '{int4,int4}', proargmodes => '{i,i}',
-  proargnames => '{cost_delay,cost_limit}', proargdefaults => '{0,100}',
-  prosrc => 'enable_data_checksums', proacl => '{POSTGRES=X}' },
-
 # collation management functions
 { oid => '3445', descr => 'import collations from operating system',
   proname => 'pg_import_system_collations', procost => '100',
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index 2a12920c75f..b5b01c1bb6d 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -188,20 +188,4 @@
 #define PROGRESS_COPY_TYPE_PIPE 3
 #define PROGRESS_COPY_TYPE_CALLBACK 4
 
-/* Progress parameters for PROGRESS_DATACHECKSUMS */
-#define PROGRESS_DATACHECKSUMS_PHASE		0
-#define PROGRESS_DATACHECKSUMS_DBS_TOTAL	1
-#define PROGRESS_DATACHECKSUMS_DBS_DONE		2
-#define PROGRESS_DATACHECKSUMS_RELS_TOTAL	3
-#define PROGRESS_DATACHECKSUMS_RELS_DONE	4
-#define PROGRESS_DATACHECKSUMS_BLOCKS_TOTAL	5
-#define PROGRESS_DATACHECKSUMS_BLOCKS_DONE	6
-
-/* Phases of datachecksumsworker operation */
-#define PROGRESS_DATACHECKSUMS_PHASE_ENABLING			0
-#define PROGRESS_DATACHECKSUMS_PHASE_DISABLING			1
-#define PROGRESS_DATACHECKSUMS_PHASE_WAITING_TEMPREL	2
-#define PROGRESS_DATACHECKSUMS_PHASE_WAITING_BARRIER	3
-#define PROGRESS_DATACHECKSUMS_PHASE_DONE				4
-
 #endif
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 0fc59af02b9..11a7d2f1542 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -370,13 +370,6 @@ typedef enum BackendType
 	B_WAL_SUMMARIZER,
 	B_WAL_WRITER,
 
-	/*
-	 * Data checksums processes are dynamic background workers, but they use
-	 * dedicated backend types for pgstat I/O accounting.
-	 */
-	B_DATACHECKSUMSWORKER_LAUNCHER,
-	B_DATACHECKSUMSWORKER_WORKER,
-
 	/*
 	 * Logger is not connected to shared memory and does not have a PGPROC
 	 * entry.
@@ -402,9 +395,6 @@ extern PGDLLIMPORT BackendType MyBackendType;
 #define AmWalSummarizerProcess()	(MyBackendType == B_WAL_SUMMARIZER)
 #define AmWalWriterProcess()		(MyBackendType == B_WAL_WRITER)
 #define AmIoWorkerProcess()			(MyBackendType == B_IO_WORKER)
-#define AmDataChecksumsWorkerProcess() \
-	(MyBackendType == B_DATACHECKSUMSWORKER_LAUNCHER || \
-	 MyBackendType == B_DATACHECKSUMSWORKER_WORKER)
 
 #define AmSpecialWorkerProcess() \
 	(AmAutoVacuumLauncherProcess() || \
diff --git a/src/include/postmaster/datachecksum_state.h b/src/include/postmaster/datachecksum_state.h
deleted file mode 100644
index f34db0c09e0..00000000000
--- a/src/include/postmaster/datachecksum_state.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * datachecksum_state.h
- *	  header file for data checksum helper background worker and data
- *	  checksum state manipulation
- *
- *
- * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/postmaster/datachecksum_state.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef DATACHECKSUM_STATE_H
-#define DATACHECKSUM_STATE_H
-
-#include "storage/procsignal.h"
-
-/* Prototypes for data checksum state manipulation */
-bool		AbsorbDataChecksumsBarrier(ProcSignalBarrierType barrier);
-void		EmitAndWaitDataChecksumsBarrier(uint32 state);
-
-/* Background worker entrypoints */
-void		DataChecksumsWorkerLauncherMain(Datum arg);
-void		DataChecksumsWorkerMain(Datum arg);
-
-#endif							/* DATACHECKSUM_STATE_H */
diff --git a/src/include/postmaster/proctypelist.h b/src/include/postmaster/proctypelist.h
index 152fde394f4..feac19ba207 100644
--- a/src/include/postmaster/proctypelist.h
+++ b/src/include/postmaster/proctypelist.h
@@ -38,8 +38,6 @@ PG_PROCTYPE(B_BACKEND, "backend", gettext_noop("client backend"), BackendMain, t
 PG_PROCTYPE(B_BG_WORKER, "bgworker", gettext_noop("background worker"), BackgroundWorkerMain, true)
 PG_PROCTYPE(B_BG_WRITER, "bgwriter", gettext_noop("background writer"), BackgroundWriterMain, true)
 PG_PROCTYPE(B_CHECKPOINTER, "checkpointer", gettext_noop("checkpointer"), CheckpointerMain, true)
-PG_PROCTYPE(B_DATACHECKSUMSWORKER_LAUNCHER, "checksums", gettext_noop("datachecksums launcher"), NULL, false)
-PG_PROCTYPE(B_DATACHECKSUMSWORKER_WORKER, "checksums", gettext_noop("datachecksums worker"), NULL, false)
 PG_PROCTYPE(B_DEAD_END_BACKEND, "backend", gettext_noop("dead-end client backend"), BackendMain, true)
 PG_PROCTYPE(B_INVALID, "postmaster", gettext_noop("unrecognized"), NULL, false)
 PG_PROCTYPE(B_IO_WORKER, "ioworker", gettext_noop("io worker"), IoWorkerMain, true)
diff --git a/src/include/replication/decode.h b/src/include/replication/decode.h
index 2ef17790205..188f1a875f7 100644
--- a/src/include/replication/decode.h
+++ b/src/include/replication/decode.h
@@ -22,7 +22,6 @@ typedef struct XLogRecordBuffer
 } XLogRecordBuffer;
 
 extern void xlog_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
-extern void xlog2_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void heap_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void heap2_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void xact_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
diff --git a/src/include/storage/checksum.h b/src/include/storage/checksum.h
index 3b1440c0c95..00d4ebc27c5 100644
--- a/src/include/storage/checksum.h
+++ b/src/include/storage/checksum.h
@@ -16,19 +16,16 @@
 #include "storage/block.h"
 
 /*
- * Checksum state 0 is used for when data checksums are disabled (OFF).
- * PG_DATA_CHECKSUM_INPROGRESS_{ON|OFF} defines that data checksums are either
- * currently being enabled or disabled, and PG_DATA_CHECKSUM_VERSION defines
- * that data checksums are enabled.  The ChecksumStateType is stored in
- * pg_control so changing requires a catversion bump, and the values cannot
- * be reordered.  New states must be added at the end.
+ * Checksum state 0 is used for when data checksums are disabled (OFF), and
+ * PG_DATA_CHECKSUM_VERSION defines that data checksums are enabled.  The
+ * ChecksumStateType is stored in pg_control so changing requires a catversion
+ * bump, and the values cannot be reordered.  New states must be added at the
+ * end.
  */
 typedef enum ChecksumStateType
 {
 	PG_DATA_CHECKSUM_OFF = 0,
 	PG_DATA_CHECKSUM_VERSION = 1,
-	PG_DATA_CHECKSUM_INPROGRESS_OFF = 2,
-	PG_DATA_CHECKSUM_INPROGRESS_ON = 3,
 } ChecksumStateType;
 
 /*
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index d7eb648bd27..272cffb0567 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -87,7 +87,6 @@ PG_LWLOCK(52, SerialControl)
 PG_LWLOCK(53, AioWorkerSubmissionQueue)
 PG_LWLOCK(54, WaitLSN)
 PG_LWLOCK(55, LogicalDecodingControl)
-PG_LWLOCK(56, DataChecksumsWorker)
 PG_LWLOCK(57, AioWorkerControl)
 
 /*
diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h
index aaa158bfd66..0a30ac05114 100644
--- a/src/include/storage/procsignal.h
+++ b/src/include/storage/procsignal.h
@@ -50,10 +50,6 @@ typedef enum
 	PROCSIGNAL_BARRIER_SMGRRELEASE, /* ask smgr to close files */
 	PROCSIGNAL_BARRIER_UPDATE_XLOG_LOGICAL_INFO,	/* ask to update
 													 * XLogLogicalInfo */
-	PROCSIGNAL_BARRIER_CHECKSUM_OFF,
-	PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON,
-	PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF,
-	PROCSIGNAL_BARRIER_CHECKSUM_ON,
 } ProcSignalBarrierType;
 
 /*
diff --git a/src/include/storage/subsystemlist.h b/src/include/storage/subsystemlist.h
index 9ad619080be..1b07e4bc957 100644
--- a/src/include/storage/subsystemlist.h
+++ b/src/include/storage/subsystemlist.h
@@ -84,7 +84,6 @@ PG_SHMEM_SUBSYSTEM(InjectionPointShmemCallbacks)
 #endif
 PG_SHMEM_SUBSYSTEM(WaitLSNShmemCallbacks)
 PG_SHMEM_SUBSYSTEM(LogicalDecodingCtlShmemCallbacks)
-PG_SHMEM_SUBSYSTEM(DataChecksumsShmemCallbacks)
 
 /* AIO subsystem. This delegates to the method-specific callbacks */
 PG_SHMEM_SUBSYSTEM(AioShmemCallbacks)
diff --git a/src/include/utils/backend_progress.h b/src/include/utils/backend_progress.h
index 61e13c40e28..6300dbd15d5 100644
--- a/src/include/utils/backend_progress.h
+++ b/src/include/utils/backend_progress.h
@@ -28,7 +28,6 @@ typedef enum ProgressCommandType
 	PROGRESS_COMMAND_BASEBACKUP,
 	PROGRESS_COMMAND_COPY,
 	PROGRESS_COMMAND_REPACK,
-	PROGRESS_COMMAND_DATACHECKSUMS,
 } ProgressCommandType;
 
 #define PGSTAT_NUM_PROGRESS_PARAM	20
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index bb88b3058ed..a11f352f70b 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -21,7 +21,6 @@ SUBDIRS = \
 		  test_bitmapset \
 		  test_bloomfilter \
 		  test_cloexec \
-		  test_checksums \
 		  test_copy_callbacks \
 		  test_custom_rmgrs \
 		  test_custom_stats \
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
index ce09e00531d..0e8c730ed8f 100644
--- a/src/test/modules/meson.build
+++ b/src/test/modules/meson.build
@@ -21,7 +21,6 @@ subdir('test_binaryheap')
 subdir('test_bitmapset')
 subdir('test_bloomfilter')
 subdir('test_cloexec')
-subdir('test_checksums')
 subdir('test_copy_callbacks')
 subdir('test_cplusplusext')
 subdir('test_custom_rmgrs')
diff --git a/src/test/modules/test_checksums/.gitignore b/src/test/modules/test_checksums/.gitignore
deleted file mode 100644
index 871e943d50e..00000000000
--- a/src/test/modules/test_checksums/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# Generated by test suite
-/tmp_check/
diff --git a/src/test/modules/test_checksums/Makefile b/src/test/modules/test_checksums/Makefile
deleted file mode 100644
index 71455cd5577..00000000000
--- a/src/test/modules/test_checksums/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-#-------------------------------------------------------------------------
-#
-# Makefile for src/test/modules/test_checksums
-#
-# Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
-# Portions Copyright (c) 1994, Regents of the University of California
-#
-# src/test/modules/test_checksums/Makefile
-#
-#-------------------------------------------------------------------------
-
-EXTRA_INSTALL = src/test/modules/injection_points
-
-export enable_injection_points
-
-MODULE_big = test_checksums
-OBJS = \
-	$(WIN32RES) \
-	test_checksums.o
-PGFILEDESC = "test_checksums - test code for data checksums"
-
-EXTENSION = test_checksums
-DATA = test_checksums--1.0.sql
-
-TAP_TESTS = 1
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = src/test/modules/test_checksums
-top_builddir = ../../../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/src/test/modules/test_checksums/README b/src/test/modules/test_checksums/README
deleted file mode 100644
index 6a23e4ff0ae..00000000000
--- a/src/test/modules/test_checksums/README
+++ /dev/null
@@ -1,30 +0,0 @@
-src/test/modules/test_checksums/README
-
-Regression tests for data checksums
-===================================
-This directory contains a test suite for enabling, and disabling, data
-checksums both offline as well as in a running cluster.
-
-Running the tests with autoconf
-===============================
-
-    make check
-
-or
-
-    make installcheck
-
-Running the tests with meson
-============================
-From your build directory, issue the following command:
-
-    meson test -q --print-errorlogs --suite setup --suite test_checksums
-
-NOTE: This creates a temporary installation (in the case of "make check" or
-"--suite setup"), with multiple nodes, be they master or standby(s) for the
-purpose of the tests.
-
-NOTE: This test suite requires TAP tests to be enabled, a subset of the tests
-also require injection points to function.  In order to run the extended test
-then "checksum_extended" must be set in the PG_TEST_EXTRA environment
-variable.
diff --git a/src/test/modules/test_checksums/meson.build b/src/test/modules/test_checksums/meson.build
deleted file mode 100644
index fb7129d796f..00000000000
--- a/src/test/modules/test_checksums/meson.build
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-test_checksums_sources = files(
-	'test_checksums.c',
-)
-
-test_checksums = shared_module('test_checksums',
-	test_checksums_sources,
-	kwargs: pg_test_mod_args,
-)
-test_install_libs += test_checksums
-
-test_install_data += files(
-	'test_checksums.control',
-	'test_checksums--1.0.sql',
-)
-
-tests += {
-  'name': 'test_checksums',
-  'sd': meson.current_source_dir(),
-  'bd': meson.current_build_dir(),
-  'tap': {
-    'env': {
-       'enable_injection_points': get_option('injection_points') ? 'yes' : 'no',
-	},
-    'tests': [
-      't/001_basic.pl',
-      't/002_restarts.pl',
-      't/003_standby_restarts.pl',
-      't/004_offline.pl',
-      't/005_injection.pl',
-      't/006_pgbench_single.pl',
-      't/007_pgbench_standby.pl',
-      't/008_pitr.pl',
-      't/009_fpi.pl',
-      't/010_backup_straddle.pl',
-      't/011_standby_straddle.pl',
-    ],
-  },
-}
diff --git a/src/test/modules/test_checksums/t/001_basic.pl b/src/test/modules/test_checksums/t/001_basic.pl
deleted file mode 100644
index 4cfd532500d..00000000000
--- a/src/test/modules/test_checksums/t/001_basic.pl
+++ /dev/null
@@ -1,221 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums in an online cluster
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# Initialize node with checksums enabled to test pg_control_init returning
-# 1 for this cluster, the remaining tests will initialize to off to test the
-# return value for a cluster initialized without checksums
-my $node = PostgreSQL::Test::Cluster->new('basic_node');
-$node->init;
-$node->start;
-
-# Create some content to have data in the cluster
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,10000) AS a;");
-
-# Ensure that checksums are turned on
-test_checksum_state($node, 'on');
-
-# Disable data checksums and wait for the state transition to 'off'
-disable_data_checksums($node, wait => 'off');
-
-# Make sure pg_control_init reports the initial enabled state
-my $result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_init();');
-is($result, '1', 'ensure pg_control_init reports enabled state');
-
-# Enable data checksums and wait for the state transition to 'on'
-enable_data_checksums($node, wait => 'on');
-
-# Run a dummy query just to make sure we can read back data
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1 ");
-is($result, '9999', 'ensure checksummed pages can be read back');
-
-# Ensure the new state is registered properly in pg_control_checkpoint()
-$result =
-  $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_checkpoint();');
-is($result, '1', 'ensure pg_control_checkpoint reports enabled state');
-# Regardless of the new state, pg_control_init() should still report checksums
-# as on.
-$result =
-  $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_init();');
-is($result, '1', 'ensure pg_control_init reports enabled state');
-
-# Enable data checksums again which should be a no-op so we explicitly don't
-# wait for any state transition as none should happen here.
-enable_data_checksums($node);
-test_checksum_state($node, 'on');
-# ..and make sure we can still read/write data
-$node->safe_psql('postgres', "UPDATE t SET a = a + 1;");
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '10000', 'ensure checksummed pages can be read back');
-
-# Disable checksums again and wait for the state transition
-disable_data_checksums($node, wait => 1);
-
-# Test reading data again
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '10000', 'ensure previously checksummed pages can be read back');
-
-# And ensure the disabled state is shown in pg_control_checkpoint()
-$result =
-  $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_checkpoint();');
-is($result, '0', 'ensure pg_control_checkpoint reports disabled state');
-
-# Re-enable checksums and make sure that the underlying data has changed to
-# ensure that checksums will be different.
-$node->safe_psql('postgres', "UPDATE t SET a = a + 1;");
-enable_data_checksums($node, wait => 'on');
-
-# Run a dummy query just to make sure we can read back the data
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '10000', 'ensure checksummed pages can be read back');
-
-# Enabling checksums in a cluster which contains an invalid database left
-# behind by an interrupted DROP DATABASE must be refused.
-disable_data_checksums($node, wait => 1);
-
-$node->safe_psql('postgres', "CREATE DATABASE baddb;");
-$node->safe_psql('baddb',
-	"CREATE TABLE bad_t AS SELECT generate_series(1,100) AS a;");
-
-# Mark the database invalid, as an interrupted DROP DATABASE would.
-$node->safe_psql('postgres',
-	"UPDATE pg_database SET datconnlimit = -2 WHERE datname = 'baddb';");
-
-# The request must fail up front with an actionable error, rather than fail
-# halfway through processing.
-my ($ret, $stdout, $stderr) =
-  $node->psql('postgres', "SELECT pg_enable_data_checksums();");
-isnt($ret, 0, 'pg_enable_data_checksums fails with an invalid database');
-like(
-	$stderr,
-	qr/invalid database "baddb"/,
-	'error message names the invalid database');
-like(
-	$stderr,
-	qr/DROP DATABASE/,
-	'error message hints at dropping the database');
-test_checksum_state($node, 'off');
-
-# Dropping the invalid database clears the way.
-$node->safe_psql('postgres', "DROP DATABASE baddb;");
-enable_data_checksums($node, wait => 'on');
-
-# A database dropped while processing is in progress is not an error, the
-# remaining databases are still processed.
-disable_data_checksums($node, wait => 1);
-
-$node->safe_psql('postgres', "CREATE DATABASE dropme;");
-$node->safe_psql('dropme',
-	"CREATE TABLE dropme_t AS SELECT generate_series(1,10000) AS a;");
-
-# Hold the worker in the "postgres" database by keeping a temporary table
-# around, the worker waits for pre-existing temp tables to disappear before
-# it reports the database as processed.  "dropme" was created last, so it is
-# processed after "postgres" and is still untouched while we wait.
-my $bg = $node->background_psql('postgres');
-$bg->query_safe('CREATE TEMP TABLE holdme (a int);');
-
-enable_data_checksums($node);
-
-$node->poll_query_until(
-	'postgres', qq[
-	SELECT count(*) > 0 FROM pg_catalog.pg_stat_activity
-	WHERE backend_type = 'datachecksums worker' AND datname = 'postgres'
-	  AND query LIKE 'Waiting for % temp tables to be removed']
-) or die "timed out waiting for worker to wait for temporary tables";
-
-# Verify the assumption that processing has not reached "dropme" yet, without
-# it the test would silently stop covering the concurrent drop.
-my $log = slurp_file($node->logfile);
-unlike(
-	$log,
-	qr/initiating data checksum processing in database "dropme"/,
-	'processing has not reached the database to drop');
-
-# Not processed yet and nobody is connected to it, so this must succeed.
-$node->safe_psql('postgres', "DROP DATABASE dropme;");
-
-# Let the worker in "postgres" finish, the launcher then moves on to the
-# database which no longer exists.
-$bg->query_safe('DROP TABLE holdme;');
-$bg->quit;
-
-wait_for_checksum_state($node, 'on');
-$node->poll_query_until('postgres',
-		"SELECT count(*) = 0 "
-	  . "FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums launcher';");
-
-# Same thing with DROP DATABASE ... WITH (FORCE), which terminates the
-# checksums worker connected to the database being dropped.
-disable_data_checksums($node, wait => 1);
-
-$node->safe_psql('postgres', "CREATE DATABASE dropmeforce;");
-$node->safe_psql('dropmeforce',
-	"CREATE TABLE dropme_t AS SELECT generate_series(1,10000) AS a;");
-
-# Hold the worker inside "dropmeforce" by keeping a temporary table around
-# there.  The session is later terminated by DROP DATABASE ... WITH (FORCE)
-# and drops the temp table while exiting; commit that drop asynchronously,
-# otherwise the exit has to flush WAL behind the traffic generated by the
-# checksum workers, which on slow machines can exceed the time DROP DATABASE
-# waits for the session to exit.
-$bg = $node->background_psql('dropmeforce');
-$bg->query_safe('SET synchronous_commit = off;');
-$bg->query_safe('CREATE TEMP TABLE holdme (a int);');
-
-enable_data_checksums($node);
-
-$node->poll_query_until(
-	'postgres', qq[
-	SELECT count(*) > 0 FROM pg_catalog.pg_stat_activity
-	WHERE backend_type = 'datachecksums worker' AND datname = 'dropmeforce'
-	  AND query LIKE 'Waiting for % temp tables to be removed']
-) or die "timed out waiting for worker to wait for temporary tables";
-
-# Write out the WAL backlog from the checksum processing so far, so that the
-# sessions terminated below do not get stuck behind it when writing their
-# final WAL records on slow machines.
-$node->safe_psql('postgres', "CHECKPOINT;");
-
-# Terminates both the session holding the temp table and the checksums
-# worker connected to the database.
-$node->safe_psql('postgres', "DROP DATABASE dropmeforce WITH (FORCE);");
-$bg->{run}->finish;
-$bg->quit;
-
-wait_for_checksum_state($node, 'on');
-$node->poll_query_until('postgres',
-		"SELECT count(*) = 0 "
-	  . "FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums launcher';");
-
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '10000', 'ensure checksummed pages can be read back');
-
-$node->stop;
-
-# The resulting cluster must also pass offline verification, proving no
-# unchecksummed files were left behind.
-command_ok(
-	[ 'pg_checksums', '--check', '-D', $node->data_dir ],
-	'offline checksum verification passes after enable');
-
-done_testing();
diff --git a/src/test/modules/test_checksums/t/002_restarts.pl b/src/test/modules/test_checksums/t/002_restarts.pl
deleted file mode 100644
index 4799afed628..00000000000
--- a/src/test/modules/test_checksums/t/002_restarts.pl
+++ /dev/null
@@ -1,160 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums in an online cluster with a
-# restart which breaks processing.
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# Initialize node with checksums disabled.
-my $node = PostgreSQL::Test::Cluster->new('restarts_node');
-$node->init(no_data_checksums => 1);
-$node->start;
-
-# Initialize result storage for queries
-my $result;
-
-# Create some content to have un-checksummed data in the cluster
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,10000) AS a;");
-
-# Ensure that checksums are disabled
-test_checksum_state($node, 'off');
-
-# Make sure pg_control_init reports the initial disabled state
-$result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_init();');
-is($result, '0', 'ensure pg_control_init reports disabled state');
-
-SKIP:
-{
-	skip 'Data checksum delay tests not enabled in PG_TEST_EXTRA', 6
-	  if (!$ENV{PG_TEST_EXTRA}
-		|| $ENV{PG_TEST_EXTRA} !~ /\bchecksum_extended\b/);
-
-	# Create a barrier for checksum enablement to block on, in this case a pre-
-	# existing temporary table which is kept open while processing is started.
-	# We can accomplish this by setting up an interactive psql process which
-	# keeps the temporary table created as we enable checksums in another psql
-	# process.
-	#
-	# This is a similar test to the synthetic variant in 005_injection.pl
-	# which fakes this scenario.
-	my $bsession = $node->background_psql('postgres');
-	$bsession->query_safe('CREATE TEMPORARY TABLE tt (a integer);');
-
-	# In another session, make sure we can see the blocking temp table but
-	# start processing anyways and check that we are blocked with a proper
-	# wait event.
-	$result = $node->safe_psql('postgres',
-		"SELECT relpersistence FROM pg_catalog.pg_class WHERE relname = 'tt';"
-	);
-	is($result, 't', 'ensure we can see the temporary table');
-
-	# Enabling data checksums shouldn't work as the process is blocked on the
-	# temporary table held open by $bsession. Ensure that we reach inprogress-
-	# on before we do more tests.
-	enable_data_checksums($node, wait => 'inprogress-on');
-
-	# Wait for processing to finish and the worker waiting for leftover temp
-	# relations to be able to actually finish
-	$result = $node->poll_query_until(
-		'postgres',
-		"SELECT wait_event FROM pg_catalog.pg_stat_activity "
-		  . "WHERE backend_type = 'datachecksums worker';",
-		'ChecksumEnableTemptableWait');
-
-	# The datachecksumsworker waits for temporary tables to disappear for 3
-	# seconds before retrying, so sleep for 4 seconds to be guaranteed to see
-	# a retry cycle
-	sleep(4);
-
-	# Re-check the wait event to ensure we are blocked on the right thing.
-	$result = $node->safe_psql('postgres',
-			"SELECT wait_event FROM pg_catalog.pg_stat_activity "
-		  . "WHERE backend_type = 'datachecksums worker';");
-	is($result, 'ChecksumEnableTemptableWait',
-		'ensure the correct wait condition is set');
-	test_checksum_state($node, 'inprogress-on');
-
-	# Stop the cluster while bsession is still attached.  We can't close the
-	# session first since the brief period between closing and stopping might
-	# be enough for checksums to get enabled.
-	$node->stop;
-	$bsession->quit;
-	$node->start;
-
-	# Ensure the checksums aren't enabled across the restart.  This leaves the
-	# cluster in the same state as before we entered the SKIP block.
-	test_checksum_state($node, 'off');
-}
-
-# Test interrupting the processing with SIGINT to make sure the launcher and
-# worker are cancelled.  Create a barrier for checksum enablement to block on
-# using the same technique as earlier with a temporary table.
-my $block_session = $node->background_psql('postgres');
-$block_session->query_safe('CREATE TEMPORARY TABLE tt (a integer);');
-
-# In another session, make sure we can see the blocking temp table but
-# start processing anyways and check that we are blocked with a proper
-# wait event.
-$result = $node->safe_psql('postgres',
-	"SELECT relpersistence FROM pg_catalog.pg_class WHERE relname = 'tt';");
-is($result, 't', 'ensure we can see the temporary table');
-
-# Ensure that we reach inprogress-on and the worker is launched and waiting for
-# the temporary table to disappear before we try to interrupt the processing.
-enable_data_checksums($node, wait => 'inprogress-on');
-$result = $node->poll_query_until(
-	'postgres',
-	"SELECT wait_event FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums worker';",
-	'ChecksumEnableTemptableWait');
-is($result, '1', 'ensure the correct wait condition is set');
-
-# Terminate launcher and worker with SIGINT
-my $pid = $node->safe_psql('postgres',
-	"SELECT pid FROM pg_catalog.pg_stat_activity WHERE backend_type = 'datachecksums launcher';"
-);
-is(PostgreSQL::Test::Utils::system_log('pg_ctl', 'kill', 'INT', $pid),
-	0, "datachecksums launcher process signalled with INT");
-
-# Wait for all processes to exit and make sure that the data_checksum state
-# was reverted back to off since we didn't finish
-$result = $node->poll_query_until(
-	'postgres',
-	"SELECT count(*) FROM pg_catalog.pg_stat_activity WHERE backend_type LIKE 'datachecksums%';",
-	'0');
-is($result, 1, 'await datachecksums worker/launcher termination');
-wait_for_checksum_state($node, "off");
-$block_session->quit;
-
-# Finish test suite by enabling checksums and make sure all data can be read
-# back, no processes are left over and the initial state is still correctly
-# reported
-enable_data_checksums($node, wait => 'on');
-
-$result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_init();');
-is($result, '0', 'ensure pg_control_init still reports disabled state');
-
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '9999', 'ensure checksummed pages can be read back');
-
-$result = $node->poll_query_until(
-	'postgres',
-	"SELECT count(*) FROM pg_catalog.pg_stat_activity WHERE backend_type LIKE 'datachecksums%';",
-	'0');
-is($result, 1, 'await datachecksums worker/launcher termination');
-
-$node->stop;
-done_testing();
diff --git a/src/test/modules/test_checksums/t/003_standby_restarts.pl b/src/test/modules/test_checksums/t/003_standby_restarts.pl
deleted file mode 100644
index b05ffd8643a..00000000000
--- a/src/test/modules/test_checksums/t/003_standby_restarts.pl
+++ /dev/null
@@ -1,288 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums in an online cluster with
-# streaming replication
-use strict;
-use warnings FATAL => 'all';
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# Initialize primary node
-my $node_primary = PostgreSQL::Test::Cluster->new('standby_restarts_primary');
-$node_primary->init(allows_streaming => 1, no_data_checksums => 1);
-$node_primary->start;
-
-my $slotname = 'physical_slot';
-$node_primary->safe_psql('postgres',
-	"SELECT pg_create_physical_replication_slot('$slotname')");
-
-# Take backup
-my $backup_name = 'my_backup';
-$node_primary->backup($backup_name);
-
-# Create streaming standby linking to primary
-my $node_standby = PostgreSQL::Test::Cluster->new('standby_restarts_standby');
-$node_standby->init_from_backup($node_primary, $backup_name,
-	has_streaming => 1);
-$node_standby->append_conf(
-	'postgresql.conf', qq[
-primary_slot_name = '$slotname'
-]);
-$node_standby->start;
-
-# Create some content on the primary to have un-checksummed data in the cluster
-$node_primary->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,10000) AS a;");
-
-# Wait for standby to catch up
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-
-# Check that checksums are turned off on all nodes
-test_checksum_state($node_primary, 'off');
-test_checksum_state($node_standby, 'off');
-
-# ---------------------------------------------------------------------------
-# Enable checksums for the cluster, and make sure that both the primary and
-# standby change state.
-#
-
-# Initiate enabling of checksums and ensure that the primary switches to
-# either "inprogress-on" or "on"
-enable_data_checksums($node_primary);
-my $result = $node_primary->poll_query_until(
-	'postgres',
-	"SELECT setting = 'off' FROM pg_catalog.pg_settings WHERE name = 'data_checksums';",
-	'f');
-is($result, 1, 'ensure primary has transitioned from off');
-# Wait for checksum enable to be replayed
-$node_primary->wait_for_catchup($node_standby, 'replay');
-
-# Ensure that the standby has switched to "inprogress-on" or "on".  Normally it
-# would be "inprogress-on", but it is theoretically possible for the primary to
-# complete the checksum enabling *and* have the standby replay that record
-# before we reach the check below.
-$result = $node_standby->poll_query_until(
-	'postgres',
-	"SELECT setting = 'off' FROM pg_catalog.pg_settings WHERE name = 'data_checksums';",
-	'f');
-is($result, 1, 'ensure standby has absorbed the inprogress-on barrier');
-$result = $node_standby->safe_psql('postgres',
-	"SELECT setting FROM pg_catalog.pg_settings WHERE name = 'data_checksums';"
-);
-
-is(($result eq 'inprogress-on' || $result eq 'on'),
-	1, 'ensure checksums are on, or in progress, on standby_1');
-
-# Insert some more data which should be checksummed on INSERT
-$node_primary->safe_psql('postgres',
-	"INSERT INTO t VALUES (generate_series(1, 10000));");
-
-# Wait for checksums enabled on the primary and standby
-wait_for_checksum_state($node_primary, 'on');
-wait_for_checksum_state($node_standby, 'on');
-
-$result =
-  $node_primary->safe_psql('postgres', "SELECT count(a) FROM t WHERE a > 1");
-is($result, '19998', 'ensure we can safely read all data with checksums');
-
-$result = $node_primary->poll_query_until(
-	'postgres',
-	"SELECT count(*) FROM pg_catalog.pg_stat_activity WHERE backend_type LIKE 'datachecksums%';",
-	'0');
-is($result, 1, 'await datachecksums worker/launcher termination');
-
-#
-# Disable checksums and ensure it's propagated to standby and that we can
-# still read all data
-#
-
-# Disable checksums and wait for the operation to be replayed
-disable_data_checksums($node_primary);
-$node_primary->wait_for_catchup($node_standby, 'replay');
-# Ensure that the primary and standby has switched to off
-wait_for_checksum_state($node_primary, 'off');
-wait_for_checksum_state($node_standby, 'off');
-# Double-check reading data without errors
-$result =
-  $node_primary->safe_psql('postgres', "SELECT count(a) FROM t WHERE a > 1");
-is($result, "19998", 'ensure we can safely read all data without checksums');
-
-# ---------------------------------------------------------------------------
-# Test that enabling checksums does not emit WAL for unlogged relations.
-# Unlogged relations are wiped on recovery, so FPIs for them would be
-# pointless and waste WAL traffic / standby I/O.
-#
-# Additionally, exercise standby promotion to ensure the init fork of an
-# unlogged relation is still WAL-logged during checksum enable -- otherwise
-# the standby keeps a stale init fork and the post-promotion main fork
-# fails verification on every read (see ResetUnloggedRelations()).  Both
-# tables must exist BEFORE enable_data_checksums() so that their init
-# forks get re-checksummed during the enable sweep.
-#
-
-$node_primary->safe_psql('postgres',
-	'CREATE UNLOGGED TABLE unlogged_tbl AS SELECT generate_series(1,1000) AS a;'
-);
-# Use a btree index so the init fork is non-trivial (one metapage).
-$node_primary->safe_psql(
-	'postgres', q[
-	CREATE UNLOGGED TABLE unlogged_promo (id int PRIMARY KEY,
-	                                      payload text);
-	INSERT INTO unlogged_promo
-	  SELECT g, repeat('x', 100) FROM generate_series(1, 1000) g;
-	CREATE INDEX unlogged_promo_payload_idx ON unlogged_promo (payload);
-]);
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-
-# Get the relfilenode and database OID so we can inspect the filesystem
-my $unlogged_rfn = $node_primary->safe_psql('postgres',
-	"SELECT relfilenode FROM pg_catalog.pg_class WHERE relname = 'unlogged_tbl';"
-);
-my $db_oid = $node_primary->safe_psql('postgres',
-	"SELECT oid FROM pg_catalog.pg_database WHERE datname = 'postgres';");
-
-# Verify the standby only has the init fork (no main fork)
-my $standby_datadir = $node_standby->data_dir;
-ok( !-f "$standby_datadir/base/$db_oid/$unlogged_rfn",
-	'standby has no main fork for unlogged table before enable');
-
-# Re-enable data checksums
-enable_data_checksums($node_primary, wait => 'on');
-wait_for_checksum_state($node_standby, 'on');
-
-# After standby replays, the unlogged main file must still not exist.
-# If the bug were present, FPI replay would materialize the full table.
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-ok( !-f "$standby_datadir/base/$db_oid/$unlogged_rfn",
-	'standby has no main fork for unlogged table after enable');
-
-# Verify unlogged relation size is 0 on the standby (main fork missing)
-my $standby_size = $node_standby->safe_psql('postgres',
-	"SELECT pg_relation_size('unlogged_tbl', 'main');");
-is($standby_size, '0',
-	'unlogged table has zero size on standby after checksum enable');
-
-# Unlogged table should still be readable on primary
-$result =
-  $node_primary->safe_psql('postgres', 'SELECT count(*) FROM unlogged_tbl;');
-is($result, '1000',
-	'unlogged table readable on primary after checksum enable');
-
-# Alter persistence to logged, and make sure we can read it on both the primary
-# and standby without any page verification errors in the logfiles.
-$node_primary->safe_psql('postgres', 'ALTER TABLE unlogged_tbl SET logged;');
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-
-$result =
-  $node_primary->safe_psql('postgres', 'SELECT sum(a) FROM unlogged_tbl;');
-is($result, '500500', 'previously unlogged table can be read on primary');
-$result =
-  $node_standby->safe_psql('postgres', 'SELECT sum(a) FROM unlogged_tbl;');
-is($result, '500500', 'previously unlogged table can be read on standby');
-
-# ---------------------------------------------------------------------------
-# Promote the standby and verify the unlogged_promo relation (created above
-# before the enable sweep) is still usable.  Without the init-fork WAL fix,
-# every read of the index would fail with
-# "page verification failed, calculated checksum X but expected 0".
-#
-$node_primary->stop;
-$node_standby->promote;
-
-$result =
-  $node_standby->safe_psql('postgres',
-	'SELECT count(*) FROM unlogged_promo;');
-is($result, '0',
-	'unlogged table readable on promoted standby (truncated as expected)');
-
-$node_standby->safe_psql('postgres',
-	"INSERT INTO unlogged_promo SELECT g, repeat('y',100) FROM generate_series(1,100) g;"
-);
-$result = $node_standby->safe_psql('postgres',
-	'SET enable_seqscan = off; SELECT id FROM unlogged_promo WHERE id = 50;');
-is($result, '50', 'indexed lookup on promoted standby returns expected row');
-
-$node_standby->stop;
-
-# Perform one final pass over the logs and hunt for unexpected errors
-my $log = PostgreSQL::Test::Utils::slurp_file($node_primary->logfile, 0);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in primary log");
-$log = PostgreSQL::Test::Utils::slurp_file($node_standby->logfile, 0);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in standby log");
-
-# ---------------------------------------------------------------------------
-# Test that enforced state transitions during promotion (via StartupXLOG) are
-# performed as expected.  When the primary crashes during inprogress-on the
-# standby should revert to off at promotion.  In order to check the transition
-# the test will keep an open psql session with the standby during promotion.
-
-# The cluster is currently broken down from the previous test.  Start up the
-# primary as primary, disable checksums and create a new standby from that
-# state.
-$node_standby->clean_node();
-$node_primary->start();
-disable_data_checksums($node_primary, wait => 'off');
-
-# Re-create a new streaming standby linking to primary.  The replication slot
-# name is reused from earlier but a fresh backup is taken
-$backup_name = 'my_new_backup';
-$node_primary->backup($backup_name);
-$node_standby = PostgreSQL::Test::Cluster->new('standby_restarts_standby');
-$node_standby->init_from_backup($node_primary, $backup_name,
-	has_streaming => 1);
-$node_standby->append_conf(
-	'postgresql.conf', qq[
-primary_slot_name = '$slotname'
-]);
-$node_standby->start;
-$node_primary->wait_for_catchup($node_standby, 'replay');
-
-# Open a background psql connection on the primary and inject a barrier to
-# block progress on to keep the state from advancing past inprogress-on
-my $node_primary_bpsql = $node_primary->background_psql('postgres');
-$node_primary_bpsql->query_safe('CREATE TEMPORARY TABLE tt (a integer);');
-# Also open a background psql connection to the standby to make sure we have
-# an active backend during promotion.
-my $node_standby_bpsql = $node_standby->background_psql('postgres');
-
-# Start to enable checksums and wait until both primary and standby have moved
-# to the inprogress-on state.  Processing will block here as the temporary rel
-# barrier will block the primary from finishing.
-enable_data_checksums($node_primary, wait => 'inprogress-on');
-$node_primary->wait_for_catchup($node_standby, 'replay');
-test_checksum_state($node_standby, 'inprogress-on');
-
-# Crash the primary before checksums are enabled and promote the standby.  The
-# new primary node will now revert the state of 'off' since checksums weren't
-# fully enabled during the crash.
-$node_primary->teardown_node();
-$node_standby->promote;
-wait_for_checksum_state($node_standby, 'off');
-
-# Ensure that the any backend which was active before, and during, promotion
-# sees the new state.
-$result = $node_standby_bpsql->query_safe("SHOW data_checksums;");
-is($result, 'off',
-	'ensure checksums are set to off after promotion during inprogress-on');
-
-$node_standby_bpsql->quit;
-$node_standby->stop;
-
-done_testing();
diff --git a/src/test/modules/test_checksums/t/004_offline.pl b/src/test/modules/test_checksums/t/004_offline.pl
deleted file mode 100644
index d0eee3afe46..00000000000
--- a/src/test/modules/test_checksums/t/004_offline.pl
+++ /dev/null
@@ -1,108 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums offline from various states
-# of checksum processing
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# Initialize node with checksums disabled.
-my $node = PostgreSQL::Test::Cluster->new('offline_node');
-$node->init(no_data_checksums => 1);
-$node->start;
-
-# Make sure pg_control_init reports the initial state as disabled
-my $result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_init();');
-is($result, '0', 'ensure pg_control_init reports disabled state');
-
-# Create some content to have un-checksummed data in the cluster
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,10000) AS a;");
-
-# Ensure that checksums are disabled
-test_checksum_state($node, 'off');
-
-# Enable checksums offline using pg_checksums
-$node->stop;
-$node->checksum_enable_offline;
-$node->start;
-
-# Ensure that checksums are enabled
-test_checksum_state($node, 'on');
-
-# Since offline checksums don't issue a checkpoint like online checksums, the
-# first call to pg_control_checkpoint will show the state as off even though
-# checksums are enabled.  After a CHECKPOINT, pg_control_checkpoint shall
-# return 1.
-$result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_checkpoint();');
-is($result, '0', 'latest checkpoint will still see off state');
-$node->safe_psql('postgres', 'CHECKPOINT;');
-$result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_checkpoint();');
-is($result, '1', 'latest checkpoint will now see on state');
-
-# Make sure pg_control_init still reports the initial state as disabled even
-# though the current state has changed.
-$result = $node->safe_psql('postgres',
-	'SELECT data_page_checksum_version FROM pg_control_init();');
-is($result, '0', 'ensure pg_control_init still reports disabled state');
-
-# Run a dummy query just to make sure we can read back some data
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '9999', 'ensure checksummed pages can be read back');
-
-# Disable checksums offline again using pg_checksums
-$node->stop;
-$node->checksum_disable_offline;
-$node->start;
-
-# Ensure that checksums are disabled
-test_checksum_state($node, 'off');
-
-# Create a barrier for checksum enablement to block on, in this case a pre-
-# existing temporary table which is kept open while processing is started. We
-# can accomplish this by setting up an interactive psql process which keeps the
-# temporary table created as we enable checksums in another psql process.
-
-my $bsession = $node->background_psql('postgres');
-$bsession->query_safe('CREATE TEMPORARY TABLE tt (a integer);');
-
-# In another session, make sure we can see the blocking temp table but start
-# processing anyways and check that we are blocked with a proper wait event.
-$result = $node->safe_psql('postgres',
-	"SELECT relpersistence FROM pg_catalog.pg_class WHERE relname = 'tt';");
-is($result, 't', 'ensure we can see the temporary table');
-
-# Enable, but stop waiting at inprogress-on since it will sit there until the
-# above temporary table is removed.
-enable_data_checksums($node, wait => 'inprogress-on');
-
-# Turn the cluster off and enable checksums offline, then start back up.
-# Stop the cluster before exiting the background session since otherwise
-# checksums might have time to get enabled before shutting down the cluster.
-$node->stop('fast');
-$bsession->quit;
-$node->checksum_enable_offline;
-$node->start;
-
-# Ensure that checksums are now enabled even though processing wasn't
-# restarted
-test_checksum_state($node, 'on');
-
-# Run a dummy query just to make sure we can read back some data
-$result = $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '9999', 'ensure checksummed pages can be read back');
-
-$node->stop;
-done_testing();
diff --git a/src/test/modules/test_checksums/t/005_injection.pl b/src/test/modules/test_checksums/t/005_injection.pl
deleted file mode 100644
index 92a4948f040..00000000000
--- a/src/test/modules/test_checksums/t/005_injection.pl
+++ /dev/null
@@ -1,215 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums in an online cluster with
-# injection point tests injecting failures into the processing
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-if ($ENV{enable_injection_points} ne 'yes')
-{
-	plan skip_all => 'Injection points not supported by this build';
-}
-
-# ---------------------------------------------------------------------------
-# Test cluster setup
-#
-
-# Initiate test cluster
-my $node = PostgreSQL::Test::Cluster->new('injection_node');
-$node->init(no_data_checksums => 1);
-$node->start;
-
-# Set up test environment
-$node->safe_psql('postgres', 'CREATE EXTENSION test_checksums;');
-$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
-
-# ---------------------------------------------------------------------------
-# Inducing failures and crashes in processing
-
-# Force enabling checksums to fail by marking one of the databases as having
-# failed in processing.
-disable_data_checksums($node, wait => 1);
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('datachecksumsworker-fail-db-result','notice');"
-);
-enable_data_checksums($node, wait => 'off');
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('datachecksumsworker-fail-db-result');");
-
-# Make sure that disabling after a failure works
-disable_data_checksums($node);
-test_checksum_state($node, 'off');
-
-# ---------------------------------------------------------------------------
-# Timing and retry related tests
-#
-
-SKIP:
-{
-	skip 'Data checksum delay tests not enabled in PG_TEST_EXTRA', 4
-	  if (!$ENV{PG_TEST_EXTRA}
-		|| $ENV{PG_TEST_EXTRA} !~ /\bchecksum_extended\b/);
-
-	# Inject a delay in the barrier for enabling checksums
-	disable_data_checksums($node, wait => 1);
-	$node->safe_psql('postgres', 'SELECT dcw_inject_delay_barrier();');
-	enable_data_checksums($node, wait => 'on');
-
-	# Fake the existence of a temporary table at the start of processing, which
-	# will force the processing to wait and retry in order to wait for it to
-	# disappear.
-	disable_data_checksums($node, wait => 1);
-	$node->safe_psql('postgres',
-		"SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait', 'notice');"
-	);
-	enable_data_checksums($node, wait => 'on');
-	$node->safe_psql('postgres',
-		"SELECT injection_points_detach('datachecksumsworker-fake-temptable-wait');"
-	);
-}
-
-# ---------------------------------------------------------------------------
-# Test an interrupted DROP DATABASE while checksum enabling is in progress
-#
-
-disable_data_checksums($node, wait => 1);
-
-$node->safe_psql('postgres', 'CREATE DATABASE invalid_dropdb;');
-$node->safe_psql('invalid_dropdb',
-	"CREATE TABLE bad_t AS SELECT generate_series(1,1000) AS a;");
-
-# Hold the worker in "postgres", so invalid_dropdb is still waiting in the
-# launcher's database list when DROP DATABASE is interrupted.
-my $hold = $node->background_psql('postgres');
-$hold->query_safe('CREATE TEMP TABLE holdme (a int);');
-
-my $dropdb_log_offset = -s $node->logfile;
-enable_data_checksums($node);
-$node->poll_query_until(
-	'postgres', qq[
-	SELECT count(*) > 0 FROM pg_catalog.pg_stat_activity
-	WHERE backend_type = 'datachecksums worker' AND datname = 'postgres'
-	  AND query LIKE 'Waiting for % temp tables to be removed']
-) or die "timed out waiting for worker to wait for temporary tables";
-
-my $dropdb_log =
-  PostgreSQL::Test::Utils::slurp_file($node->logfile, $dropdb_log_offset);
-unlike(
-	$dropdb_log,
-	qr/initiating data checksum processing in database "invalid_dropdb"/,
-	'invalid database has not been processed yet');
-
-# Leave the database durably marked invalid, but abort DROP DATABASE before
-# its catalog row and files are removed.
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('dropdb-after-invalid-marker','error');");
-my ($drop_ret, $drop_stdout, $drop_stderr) =
-  $node->psql('postgres', 'DROP DATABASE invalid_dropdb;');
-isnt($drop_ret, 0, 'DROP DATABASE was interrupted after invalidation');
-like(
-	$drop_stderr,
-	qr/dropdb-after-invalid-marker/,
-	'DROP DATABASE reached the invalid-marker injection point');
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('dropdb-after-invalid-marker');");
-
-my $invalid_state = $node->safe_psql('postgres',
-	"SELECT datconnlimit FROM pg_catalog.pg_database WHERE datname = 'invalid_dropdb';"
-);
-is($invalid_state, '-2', 'interrupted DROP left an invalid database row');
-
-# Let checksum processing continue.  The invalid database must be treated as
-# a processing failure, not as a successfully dropped database.
-$hold->query_safe('DROP TABLE holdme;');
-$hold->quit;
-$node->poll_query_until('postgres',
-		"SELECT count(*) = 0 "
-	  . "FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums launcher';")
-  or die "timed out waiting for datachecksums launcher to exit";
-test_checksum_state($node, 'off');
-
-# Remove the invalid database and continue with the remaining tests.
-$node->safe_psql('postgres', 'DROP DATABASE invalid_dropdb;');
-
-# ---------------------------------------------------------------------------
-# Test concurrent CREATE DATABASE which use the file_copy strategy
-#
-
-disable_data_checksums($node, wait => 1);
-my $node_loglocation = -s $node->logfile;
-
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,10000) AS a;");
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('createdb-before-catalog-insert','wait');"
-);
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait','wait');"
-);
-
-# Hold CREATE DATABASE after the strategy check, before its xact is visible.
-my $bg = $node->background_psql('postgres');
-$bg->query_until(
-	qr/starting_create/, q(
-\echo starting_create
-CREATE DATABASE fcdb TEMPLATE template0 STRATEGY file_copy;
-));
-$node->wait_for_event('client backend', 'createdb-before-catalog-insert');
-
-# Enable checksums, worker holds before processing template0.
-enable_data_checksums($node);
-$node->wait_for_event('datachecksums worker',
-	'datachecksumsworker-fake-temptable-wait');
-
-# Release CREATE DATABASE, must fail on the recheck instead of raw-copying.
-$node->safe_psql('postgres',
-	"SELECT injection_points_wakeup('createdb-before-catalog-insert');");
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('createdb-before-catalog-insert');");
-
-# Wait for the CREATE DATABASE xact to finish before releasing the worker.
-$node->poll_query_until('postgres',
-		"SELECT count(*) = 0 FROM pg_catalog.pg_stat_activity "
-	  . "WHERE query LIKE 'CREATE DATABASE%' AND state != 'idle';");
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_wakeup('datachecksumsworker-fake-temptable-wait');"
-);
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('datachecksumsworker-fake-temptable-wait');"
-);
-
-wait_for_checksum_state($node, 'on');
-
-my $result = $node->safe_psql('postgres',
-	"SELECT count(*) FROM pg_catalog.pg_database WHERE datname = 'fcdb';");
-is($result, '0', 'file_copy database creation was refused');
-
-my $log =
-  PostgreSQL::Test::Utils::slurp_file($node->logfile, $node_loglocation);
-like(
-	$log,
-	qr/create database strategy "file_copy" not allowed/m,
-	'file_copy error message in log');
-
-# ---------------------------------------------------------------------------
-# Test teardown
-#
-
-$bg->{run}->finish;
-$bg->quit;
-$node->stop;
-done_testing();
diff --git a/src/test/modules/test_checksums/t/006_pgbench_single.pl b/src/test/modules/test_checksums/t/006_pgbench_single.pl
deleted file mode 100644
index b0ccf05fce9..00000000000
--- a/src/test/modules/test_checksums/t/006_pgbench_single.pl
+++ /dev/null
@@ -1,285 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums in an online cluster with
-# concurrent activity via pgbench runs
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# This test suite is expensive, or very expensive, to execute.  There are two
-# PG_TEST_EXTRA options for running it, "checksum" for a pared-down test suite
-# an "checksum_extended" for the full suite.  The full suite can run for hours
-# on slow or constrained systems.
-my $extended = undef;
-if ($ENV{PG_TEST_EXTRA})
-{
-	$extended = 1 if ($ENV{PG_TEST_EXTRA} =~ /\bchecksum_extended\b/);
-	plan skip_all => 'Expensive data checksums test disabled'
-	  unless ($ENV{PG_TEST_EXTRA} =~ /\bchecksum(_extended)?\b/);
-}
-else
-{
-	plan skip_all => 'Expensive data checksums test disabled';
-}
-
-if ($ENV{enable_injection_points} ne 'yes')
-{
-	plan skip_all => 'Injection points not supported by this build';
-}
-
-my $node;
-my $node_loglocation = 0;
-
-# The number of full test iterations which will be performed. The exact number
-# of tests performed and the wall time taken is non-deterministic as the test
-# performs a lot of randomized actions, but 10 iterations will be a long test
-# run regardless.
-my $TEST_ITERATIONS = 1;
-$TEST_ITERATIONS = 10 if ($extended);
-
-# Variables which record the current state of the cluster
-my $data_checksum_state = 'off';
-my $pgbench = undef;
-
-# Start a pgbench run in the background against the server specified via the
-# port passed as parameter.
-sub background_rw_pgbench
-{
-	my $port = shift;
-
-	# If a previous pgbench is still running, start by shutting it down.
-	$pgbench->finish if $pgbench;
-
-	my $clients = 1;
-	my $runtime = 2;
-
-	if ($extended)
-	{
-		# Randomize the number of pgbench clients a bit (range 1-16)
-		$clients = 1 + int(rand(15));
-		$runtime = 600;
-	}
-	my @cmd = ('pgbench', '-p', $port, '-T', $runtime, '-c', $clients);
-
-	# Randomize whether we spawn connections or not
-	push(@cmd, '-C') if ($extended && cointoss);
-	# Finally add the database name to use
-	push(@cmd, 'postgres');
-
-	$pgbench = IPC::Run::start(
-		\@cmd,
-		'<' => '/dev/null',
-		'>' => '/dev/null',
-		'2>' => '/dev/null',
-		IPC::Run::timer($PostgreSQL::Test::Utils::timeout_default));
-}
-
-# Invert the state of data checksums in the cluster, if data checksums are on
-# then disable them and vice versa. Also performs proper validation of the
-# before and after state.
-sub flip_data_checksums
-{
-	my $temptablewait = 0;
-
-	# First, make sure the cluster is in the state we expect it to be
-	test_checksum_state($node, $data_checksum_state);
-
-	if ($data_checksum_state eq 'off')
-	{
-		# Coin-toss to see if we are injecting a retry due to a temptable
-		if (cointoss())
-		{
-			$node->safe_psql('postgres',
-				"SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait', 'notice');"
-			);
-			$temptablewait = 1;
-		}
-
-		# log LSN right before we start changing checksums
-		my $result =
-		  $node->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN before enabling: " . $result . "\n");
-
-		# Ensure that the primary switches to "inprogress-on"
-		enable_data_checksums($node, wait => 'inprogress-on');
-
-		random_sleep() if ($extended);
-
-		# Wait for checksums enabled on the primary
-		wait_for_checksum_state($node, 'on');
-
-		# log LSN right after the primary flips checksums to "on"
-		$result = $node->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN after enabling: " . $result . "\n");
-
-		random_sleep() if ($extended);
-
-		$node->safe_psql('postgres',
-			"SELECT injection_points_detach('datachecksumsworker-fake-temptable-wait');"
-		) if ($temptablewait);
-		$data_checksum_state = 'on';
-	}
-	elsif ($data_checksum_state eq 'on')
-	{
-		random_sleep() if ($extended);
-
-		# log LSN right before we start changing checksums
-		my $result =
-		  $node->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN before disabling: " . $result . "\n");
-
-		disable_data_checksums($node);
-
-		# Wait for checksums disabled on the primary
-		wait_for_checksum_state($node, 'off');
-
-		# log LSN right after the primary flips checksums to "off"
-		$result = $node->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN after disabling: " . $result . "\n");
-
-		random_sleep() if ($extended);
-
-		$data_checksum_state = 'off';
-	}
-	else
-	{
-		# This should only happen due to programmer error when hacking on the
-		# test code, but since that might pass subtly we error out.
-		BAIL_OUT('data_checksum_state variable has invalid state:'
-			  . $data_checksum_state);
-	}
-}
-
-# Create and start a cluster with one node
-$node = PostgreSQL::Test::Cluster->new('pgbench_single_main');
-$node->init(allows_streaming => 1, no_data_checksums => 1);
-# max_connections need to be bumped in order to accommodate for pgbench clients
-# and log_statement is dialled down since it otherwise will generate enormous
-# amounts of logging. Page verification failures are still logged.
-$node->append_conf(
-	'postgresql.conf',
-	qq[
-max_connections = 100
-log_statement = none
-]);
-$node->start;
-$node->safe_psql('postgres', 'CREATE EXTENSION test_checksums;');
-$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
-# Create some content to have un-checksummed data in the cluster
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1, 100000) AS a;");
-# Initialize pgbench
-my $scalefactor = ($extended ? 10 : 1);
-$node->command_ok(
-	[
-		'pgbench', '-p', $node->port, '-i',
-		'-s', $scalefactor, '-q', 'postgres'
-	]);
-# Start the test suite with pgbench running.
-background_rw_pgbench($node->port);
-
-# Main test suite. This loop will start a pgbench run on the cluster and while
-# that's running flip the state of data checksums concurrently. It will then
-# randomly restart the cluster and then check for
-# the desired state.  The idea behind doing things randomly is to stress out
-# any timing related issues by subjecting the cluster for varied workloads.
-# A TODO is to generate a trace such that any test failure can be traced to
-# its order of operations for debugging.
-for (my $i = 0; $i < $TEST_ITERATIONS; $i++)
-{
-	note("iteration ", ($i + 1), " of ", $TEST_ITERATIONS);
-
-	if (!$node->is_alive)
-	{
-		# Start, to do recovery, and stop
-		$node->start;
-		$node->stop('fast');
-
-		# Since the log isn't being written to now, parse the log and check
-		# for instances of checksum verification failures.
-		my $log = PostgreSQL::Test::Utils::slurp_file($node->logfile,
-			$node_loglocation);
-		unlike(
-			$log,
-			qr/page verification failed,.+\d$/m,
-			"no checksum validation errors in primary log (during WAL recovery)"
-		);
-		$node_loglocation = -s $node->logfile;
-
-		# Randomize the WAL size, to trigger checkpoints less/more often
-		my $sb = 64 + int(rand(1024));
-		$node->append_conf('postgresql.conf', qq[max_wal_size = $sb]);
-		note("changing max_wal_size to " . $sb);
-
-		$node->start;
-
-		# Start a pgbench in the background against the primary
-		background_rw_pgbench($node->port);
-	}
-
-	$node->safe_psql('postgres', "UPDATE t SET a = a + 1;");
-
-	flip_data_checksums();
-	random_sleep() if ($extended);
-	my $result =
-	  $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-	is($result, '100000', 'ensure data pages can be read back on primary');
-
-	random_sleep() if ($extended);
-
-	# Potentially powercycle the node
-	if (cointoss())
-	{
-		$node->stop(stopmode());
-
-		PostgreSQL::Test::Utils::system_log("pg_controldata",
-			$node->data_dir);
-
-		my $log = PostgreSQL::Test::Utils::slurp_file($node->logfile,
-			$node_loglocation);
-		unlike(
-			$log,
-			qr/page verification failed,.+\d$/m,
-			"no checksum validation errors in primary log (outside WAL recovery)"
-		);
-		$node_loglocation = -s $node->logfile;
-	}
-
-	random_sleep() if ($extended);
-}
-
-# Make sure the node is running
-if (!$node->is_alive)
-{
-	$node->start;
-}
-
-# Testrun is over, ensure that data reads back as expected and perform a final
-# verification of the data checksum state.
-my $result =
-  $node->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '100000', 'ensure data pages can be read back on primary');
-test_checksum_state($node, $data_checksum_state);
-
-# Perform one final pass over the logs and hunt for unexpected errors
-my $log =
-  PostgreSQL::Test::Utils::slurp_file($node->logfile, $node_loglocation);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in primary log");
-$node_loglocation = -s $node->logfile;
-
-$node->teardown_node;
-
-done_testing();
diff --git a/src/test/modules/test_checksums/t/007_pgbench_standby.pl b/src/test/modules/test_checksums/t/007_pgbench_standby.pl
deleted file mode 100644
index 38e17ca38ee..00000000000
--- a/src/test/modules/test_checksums/t/007_pgbench_standby.pl
+++ /dev/null
@@ -1,411 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test suite for testing enabling data checksums in an online cluster,
-# comprising of a primary and a replicated standby, with concurrent activity
-# via pgbench runs
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# This test suite is expensive, or very expensive, to execute.  There are two
-# PG_TEST_EXTRA options for running it, "checksum" for a pared-down test suite
-# an "checksum_extended" for the full suite.  The full suite can run for hours
-# on slow or constrained systems.
-my $extended = undef;
-if ($ENV{PG_TEST_EXTRA})
-{
-	$extended = 1 if ($ENV{PG_TEST_EXTRA} =~ /\bchecksum_extended\b/);
-	plan skip_all => 'Expensive data checksums test disabled'
-	  unless ($ENV{PG_TEST_EXTRA} =~ /\bchecksum(_extended)?\b/);
-}
-else
-{
-	plan skip_all => 'Expensive data checksums test disabled';
-}
-
-if ($ENV{enable_injection_points} ne 'yes')
-{
-	plan skip_all => 'Injection points not supported by this build';
-}
-
-my $node_primary_slot = 'physical_slot';
-my $node_primary_backup = 'primary_backup';
-my $node_primary;
-my $node_primary_loglocation = 0;
-my $node_standby;
-my $node_standby_loglocation = 0;
-
-# The number of full test iterations which will be performed. The exact number
-# of tests performed and the wall time taken is non-deterministic as the test
-# performs a lot of randomized actions, but 5 iterations will be a long test
-# run regardless.
-my $TEST_ITERATIONS = 1;
-$TEST_ITERATIONS = 5 if ($extended);
-
-# Variables which record the current state of the cluster
-my $data_checksum_state = 'off';
-
-my $pgbench_primary = undef;
-my $pgbench_standby = undef;
-
-# Start a pgbench run in the background against the server specified via the
-# port passed as parameter
-sub background_pgbench
-{
-	my ($port, $standby) = @_;
-	my $pgbench = ($standby ? \$pgbench_standby : \$pgbench_primary);
-
-	# Terminate any currently running pgbench process before continuing
-	$$pgbench->finish if $$pgbench;
-
-	my $clients = 1;
-	my $runtime = 5;
-
-	if ($extended)
-	{
-		# Randomize the number of pgbench clients a bit (range 1-16)
-		$clients = 1 + int(rand(15));
-		$runtime = 600;
-	}
-
-	my @cmd = ('pgbench', '-p', $port, '-T', $runtime, '-c', $clients);
-	# Randomize whether we spawn connections or not
-	push(@cmd, '-C') if ($extended && cointoss());
-	# If we run on a standby it needs to be a read-only benchmark
-	push(@cmd, '-S') if ($standby);
-	push(@cmd, '-n') if ($standby);
-	# Finally add the database name to use
-	push(@cmd, 'postgres');
-
-	$$pgbench = IPC::Run::start(
-		\@cmd,
-		'<' => '/dev/null',
-		'>' => '/dev/null',
-		'2>' => '/dev/null',
-		IPC::Run::timer($PostgreSQL::Test::Utils::timeout_default));
-}
-
-# Invert the state of data checksums in the cluster, if data checksums are on
-# then disable them and vice versa. Also performs proper validation of the
-# before and after state.
-sub flip_data_checksums
-{
-	my $temptablewait = 0;
-
-	# First, make sure the cluster is in the state we expect it to be
-	test_checksum_state($node_primary, $data_checksum_state);
-	test_checksum_state($node_standby, $data_checksum_state);
-
-	if ($data_checksum_state eq 'off')
-	{
-		# Coin-toss to see if we are injecting a retry due to a temptable
-		if (cointoss())
-		{
-			$node_primary->safe_psql('postgres',
-				"SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait', 'notice');"
-			);
-			$temptablewait = 1;
-		}
-
-		# log LSN right before we start changing checksums
-		my $result =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN before enabling: " . $result . "\n");
-
-		# Ensure that the primary switches to "inprogress-on"
-		enable_data_checksums($node_primary, wait => 'inprogress-on');
-
-		random_sleep() if ($extended);
-
-		# Wait for checksum enable to be replayed
-		$node_primary->wait_for_catchup($node_standby, 'replay');
-
-		# Ensure that the standby has switched to "inprogress-on" or "on".
-		# Normally it would be "inprogress-on", but it is theoretically
-		# possible for the primary to complete the checksum enabling *and* have
-		# the standby replay that record before we reach the check below.
-		$result = $node_standby->poll_query_until(
-			'postgres',
-			"SELECT setting = 'off' "
-			  . "FROM pg_catalog.pg_settings "
-			  . "WHERE name = 'data_checksums';",
-			'f');
-		is($result, 1,
-			'ensure standby has absorbed the inprogress-on barrier');
-		$result = $node_standby->safe_psql('postgres',
-				"SELECT setting "
-			  . "FROM pg_catalog.pg_settings "
-			  . "WHERE name = 'data_checksums';");
-
-		is( ($result eq 'inprogress-on' || $result eq 'on'),
-			1,
-			'ensure checksums are on, or in progress, on standby_1, got: '
-			  . $result);
-
-		# Wait for checksums enabled on the primary and standby
-		wait_for_checksum_state($node_primary, 'on');
-
-		# log LSN right after the primary flips checksums to "on"
-		$result =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN after enabling: " . $result . "\n");
-
-		random_sleep() if ($extended);
-		wait_for_checksum_state($node_standby, 'on');
-
-		$node_primary->safe_psql('postgres',
-			"SELECT injection_points_detach('datachecksumsworker-fake-temptable-wait');"
-		) if ($temptablewait);
-		$data_checksum_state = 'on';
-	}
-	elsif ($data_checksum_state eq 'on')
-	{
-		random_sleep() if ($extended);
-
-		# log LSN right before we start changing checksums
-		my $result =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN before disabling: " . $result . "\n");
-
-		disable_data_checksums($node_primary);
-		$node_primary->wait_for_catchup($node_standby, 'replay');
-
-		# Wait for checksums disabled on the primary and standby
-		random_sleep() if ($extended);
-		wait_for_checksum_state($node_primary, 'off');
-		wait_for_checksum_state($node_standby, 'off');
-
-		# log LSN right after the primary flips checksums to "off"
-		$result =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN after disabling: " . $result . "\n");
-
-		$data_checksum_state = 'off';
-	}
-	else
-	{
-		# This should only happen due to programmer error when hacking on the
-		# test code, but since that might pass subtly we error out.
-		BAIL_OUT('data_checksum_state variable has invalid state:'
-			  . $data_checksum_state);
-	}
-}
-
-# Create and start a cluster with one primary and one standby node, and ensure
-# they are caught up and in sync.
-$node_primary = PostgreSQL::Test::Cluster->new('pgbench_standby_main');
-$node_primary->init(allows_streaming => 1, no_data_checksums => 1);
-# max_connections need to be bumped in order to accommodate for pgbench clients
-# and log_statement is dialled down since it otherwise will generate enormous
-# amounts of logging. Page verification failures are still logged.
-$node_primary->append_conf(
-	'postgresql.conf',
-	qq[
-max_connections = 30
-log_statement = none
-hot_standby_feedback = on
-]);
-$node_primary->start;
-$node_primary->safe_psql('postgres', 'CREATE EXTENSION test_checksums;');
-$node_primary->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
-# Create some content to have un-checksummed data in the cluster
-$node_primary->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1, 100000) AS a;");
-$node_primary->safe_psql('postgres',
-	"SELECT pg_create_physical_replication_slot('$node_primary_slot');");
-$node_primary->backup($node_primary_backup);
-
-$node_standby = PostgreSQL::Test::Cluster->new('pgbench_standby_standby');
-$node_standby->init_from_backup($node_primary, $node_primary_backup,
-	has_streaming => 1);
-$node_standby->append_conf(
-	'postgresql.conf', qq[
-primary_slot_name = '$node_primary_slot'
-]);
-$node_standby->start;
-
-# Initialize pgbench and wait for the objects to be created on the standby
-my $scalefactor = ($extended ? 10 : 1);
-$node_primary->command_ok(
-	[
-		'pgbench', '-p', $node_primary->port, '-i', '-s', $scalefactor, '-q',
-		'postgres'
-	]);
-$node_primary->wait_for_catchup($node_standby, 'replay');
-
-# Start the test suite with pgbench running on all nodes
-background_pgbench($node_standby->port, 1);
-background_pgbench($node_primary->port, 0);
-
-# Main test suite. This loop will start a pgbench run on the cluster and while
-# that's running flip the state of data checksums concurrently. It will then
-# randomly restart the cluster and then check for
-# the desired state.  The idea behind doing things randomly is to stress out
-# any timing related issues by subjecting the cluster for varied workloads.
-# A TODO is to generate a trace such that any test failure can be traced to
-# its order of operations for debugging.
-for (my $i = 0; $i < $TEST_ITERATIONS; $i++)
-{
-	note("iteration ", ($i + 1), " of ", $TEST_ITERATIONS);
-
-	if (!$node_primary->is_alive)
-	{
-		# start, to do recovery, and stop
-		$node_primary->start;
-		$node_primary->stop('fast');
-
-		# Since the log isn't being written to now, parse the log and check
-		# for instances of checksum verification failures.
-		my $log = PostgreSQL::Test::Utils::slurp_file($node_primary->logfile,
-			$node_primary_loglocation);
-		unlike(
-			$log,
-			qr/page verification failed,.+\d$/m,
-			"no checksum validation errors in primary log (during WAL recovery)"
-		);
-		$node_primary_loglocation = -s $node_primary->logfile;
-
-		# randomize the WAL size, to trigger checkpoints less/more often
-		my $sb = 32 + int(rand(960));
-		$node_primary->append_conf('postgresql.conf', qq[max_wal_size = $sb]);
-
-		note("changing primary max_wal_size to " . $sb);
-
-		$node_primary->start;
-
-		# Start a pgbench in the background against the primary
-		background_pgbench($node_primary->port, 0);
-	}
-
-	if (!$node_standby->is_alive)
-	{
-		$node_standby->start;
-		$node_standby->stop('fast');
-
-		# Since the log isn't being written to now, parse the log and check
-		# for instances of checksum verification failures.
-		my $log =
-		  PostgreSQL::Test::Utils::slurp_file($node_standby->logfile,
-			$node_standby_loglocation);
-		unlike(
-			$log,
-			qr/page verification failed,.+\d$/m,
-			"no checksum validation errors in standby_1 log (during WAL recovery)"
-		);
-		$node_standby_loglocation = -s $node_standby->logfile;
-
-		# randomize the WAL size, to trigger checkpoints less/more often
-		my $sb = 32 + int(rand(960));
-		$node_standby->append_conf('postgresql.conf', qq[max_wal_size = $sb]);
-
-		note("changing standby max_wal_size to " . $sb);
-
-		$node_standby->start;
-
-		# Start a read-only pgbench in the background on the standby
-		background_pgbench($node_standby->port, 1);
-	}
-
-	$node_primary->safe_psql('postgres', "UPDATE t SET a = a + 1;");
-	$node_primary->wait_for_catchup($node_standby, 'write');
-
-	flip_data_checksums();
-	random_sleep() if ($extended);
-	my $result = $node_primary->safe_psql('postgres',
-		"SELECT count(*) FROM t WHERE a > 1");
-	is($result, '100000', 'ensure data pages can be read back on primary');
-	random_sleep();
-
-	# Potentially powercycle the cluster (the nodes independently). A TODO is
-	# to randomly stop the nodes in the opposite order too.
-	if ($extended && cointoss())
-	{
-		$node_primary->stop(stopmode());
-
-		# print the contents of the control file on the primary
-		PostgreSQL::Test::Utils::system_log("pg_controldata",
-			$node_primary->data_dir);
-
-		# slurp the file after shutdown, so that it doesn't interfere with the recovery
-		my $log = PostgreSQL::Test::Utils::slurp_file($node_primary->logfile,
-			$node_primary_loglocation);
-		unlike(
-			$log,
-			qr/page verification failed,.+\d$/m,
-			"no checksum validation errors in primary log (outside WAL recovery)"
-		);
-		$node_primary_loglocation = -s $node_primary->logfile;
-	}
-
-	random_sleep() if ($extended);
-
-	if ($extended && cointoss())
-	{
-		$node_standby->stop(stopmode());
-
-		# print the contents of the control file on the standby
-		PostgreSQL::Test::Utils::system_log("pg_controldata",
-			$node_standby->data_dir);
-
-		# slurp the file after shutdown, so that it doesn't interfere with the recovery
-		my $log =
-		  PostgreSQL::Test::Utils::slurp_file($node_standby->logfile,
-			$node_standby_loglocation);
-		unlike(
-			$log,
-			qr/page verification failed,.+\d$/m,
-			"no checksum validation errors in standby_1 log (outside WAL recovery)"
-		);
-		$node_standby_loglocation = -s $node_standby->logfile;
-	}
-}
-
-# make sure the nodes are running
-if (!$node_primary->is_alive)
-{
-	$node_primary->start;
-}
-
-if (!$node_standby->is_alive)
-{
-	$node_standby->start;
-}
-
-# Testrun is over, ensure that data reads back as expected and perform a final
-# verification of the data checksum state.
-my $result =
-  $node_primary->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '100000', 'ensure data pages can be read back on primary');
-test_checksum_state($node_primary, $data_checksum_state);
-test_checksum_state($node_standby, $data_checksum_state);
-
-# Perform one final pass over the logs and hunt for unexpected errors
-my $log = PostgreSQL::Test::Utils::slurp_file($node_primary->logfile,
-	$node_primary_loglocation);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in primary log");
-$node_primary_loglocation = -s $node_primary->logfile;
-$log = PostgreSQL::Test::Utils::slurp_file($node_standby->logfile,
-	$node_standby_loglocation);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in standby_1 log");
-$node_standby_loglocation = -s $node_standby->logfile;
-
-$node_standby->teardown_node;
-$node_primary->teardown_node;
-
-done_testing();
diff --git a/src/test/modules/test_checksums/t/008_pitr.pl b/src/test/modules/test_checksums/t/008_pitr.pl
deleted file mode 100644
index 913377c9d32..00000000000
--- a/src/test/modules/test_checksums/t/008_pitr.pl
+++ /dev/null
@@ -1,192 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# This test suite is expensive, or very expensive, to execute.  There are two
-# PG_TEST_EXTRA options for running it, "checksum" for a pared-down test suite
-# an "checksum_extended" for the full suite.
-my $extended = undef;
-if ($ENV{PG_TEST_EXTRA})
-{
-	$extended = 1 if ($ENV{PG_TEST_EXTRA} =~ /\bchecksum_extended\b/);
-	plan skip_all => 'Expensive data checksums test disabled'
-	  unless ($ENV{PG_TEST_EXTRA} =~ /\bchecksum(_extended)?\b/);
-}
-else
-{
-	plan skip_all => 'Expensive data checksums test disabled';
-}
-
-
-my $pgbench = undef;
-my $data_checksum_state = 'off';
-
-my $node_primary;
-
-# Invert the state of data checksums in the cluster, if data checksums are on
-# then disable them and vice versa. Also performs proper validation of the
-# before and after state.
-sub flip_data_checksums
-{
-	my $lsn_pre = undef;
-	my $lsn_post = undef;
-
-	# First, make sure the cluster is in the state we expect it to be
-	test_checksum_state($node_primary, $data_checksum_state);
-
-	if ($data_checksum_state eq 'off')
-	{
-		# log LSN right before we start changing checksums
-		$lsn_pre =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN before enabling: " . $lsn_pre . "\n");
-
-		# Wait for checksums enabled on the primary
-		enable_data_checksums($node_primary, wait => 'on');
-
-		# log LSN right after the primary flips checksums to "on"
-		$lsn_post =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN after enabling: " . $lsn_post . "\n");
-
-		$data_checksum_state = 'on';
-	}
-	elsif ($data_checksum_state eq 'on')
-	{
-		# log LSN right before we start changing checksums
-		$lsn_pre =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN before disabling: " . $lsn_pre . "\n");
-
-		# Disable checksums on the primary and wait for completion
-		disable_data_checksums($node_primary, wait => 1);
-
-		# log LSN right after the primary flips checksums to "off"
-		$lsn_post =
-		  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
-		note("LSN after disabling: " . $lsn_post . "\n");
-
-		$data_checksum_state = 'off';
-	}
-	else
-	{
-		# This should only happen due to programmer error when hacking on the
-		# test code, but since that might pass subtly we error out.
-		BAIL_OUT('data_checksum_state variable has invalid state:'
-			  . $data_checksum_state);
-	}
-
-	return ($lsn_pre, $lsn_post);
-}
-# Start a pgbench run in the background against the server specified via the
-# port passed as parameter.
-sub background_rw_pgbench
-{
-	my $port = shift;
-
-	# If a previous pgbench is still running, start by shutting it down.
-	$pgbench->finish if $pgbench;
-
-	# Randomize the number of pgbench clients in extended mode, else 1 client
-	my $clients = ($extended ? 1 + int(rand(15)) : 1);
-	my $runtime = ($extended ? 600 : 5);
-
-	my @cmd = ('pgbench', '-p', $port, '-T', $runtime, '-c', $clients);
-
-	# Randomize whether we spawn connections or not
-	push(@cmd, '-C') if ($extended && cointoss());
-	# Finally add the database name to use
-	push(@cmd, 'postgres');
-
-	$pgbench = IPC::Run::start(
-		\@cmd,
-		'<' => '/dev/null',
-		'>' => '/dev/null',
-		'2>' => '/dev/null',
-		IPC::Run::timer($PostgreSQL::Test::Utils::timeout_default));
-}
-
-# Start a primary node with WAL archiving enabled and with enough connections
-# available to handle pgbench clients.
-$node_primary = PostgreSQL::Test::Cluster->new('pitr_main');
-$node_primary->init(
-	has_archiving => 1,
-	allows_streaming => 1,
-	no_data_checksums => 1);
-my $timeout_unit = 's';
-$node_primary->append_conf(
-	'postgresql.conf',
-	qq[
-max_connections = 100
-log_statement = none
-wal_sender_timeout = $PostgreSQL::Test::Utils::timeout_default$timeout_unit
-wal_receiver_timeout = $PostgreSQL::Test::Utils::timeout_default$timeout_unit
-]);
-$node_primary->start;
-
-# Prime the cluster with a bit of known data which we can read back to check
-# for data consistency as well as page verification faults in the logfile.
-$node_primary->safe_psql('postgres',
-	'CREATE TABLE t AS SELECT generate_series(1, 100000) AS a;');
-# Initialize and start pgbench in read/write mode against the cluster
-my $scalefactor = ($extended ? 10 : 1);
-$node_primary->command_ok(
-	[
-		'pgbench', '-p', $node_primary->port, '-i', '-s', $scalefactor, '-q',
-		'postgres'
-	]);
-background_rw_pgbench($node_primary->port);
-
-# Take a backup to use for PITR
-my $backup_name = 'my_backup';
-$node_primary->backup($backup_name);
-
-my ($pre_lsn, $post_lsn) = flip_data_checksums();
-
-$node_primary->safe_psql('postgres', "UPDATE t SET a = a + 1;");
-$node_primary->safe_psql('postgres', "SELECT pg_create_restore_point('a');");
-$node_primary->safe_psql('postgres', "UPDATE t SET a = a + 1;");
-$node_primary->stop('fast');
-
-my $node_pitr = PostgreSQL::Test::Cluster->new('pitr_backup');
-$node_pitr->init_from_backup(
-	$node_primary, $backup_name,
-	standby => 0,
-	has_restoring => 1);
-$node_pitr->append_conf(
-	'postgresql.conf', qq{
-recovery_target_lsn = '$post_lsn'
-recovery_target_action = 'promote'
-recovery_target_inclusive = on
-});
-
-$node_pitr->start;
-
-$node_pitr->poll_query_until('postgres', "SELECT pg_is_in_recovery() = 'f';")
-  or die "Timed out while waiting for PITR promotion";
-
-test_checksum_state($node_pitr, $data_checksum_state);
-my $result =
-  $node_pitr->safe_psql('postgres', "SELECT count(*) FROM t WHERE a > 1");
-is($result, '99999', 'ensure data pages can be read back on primary');
-
-$node_pitr->stop;
-
-my $log = PostgreSQL::Test::Utils::slurp_file($node_pitr->logfile, 0);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in pitr log");
-
-done_testing();
diff --git a/src/test/modules/test_checksums/t/009_fpi.pl b/src/test/modules/test_checksums/t/009_fpi.pl
deleted file mode 100644
index 1a7dcd0e15d..00000000000
--- a/src/test/modules/test_checksums/t/009_fpi.pl
+++ /dev/null
@@ -1,64 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# Create and start a cluster with one node
-my $node = PostgreSQL::Test::Cluster->new('fpi_node');
-$node->init(allows_streaming => 1, no_data_checksums => 1);
-# max_connections need to be bumped in order to accommodate for pgbench clients
-# and log_statement is dialled down since it otherwise will generate enormous
-# amounts of logging. Page verification failures are still logged.
-$node->append_conf(
-	'postgresql.conf',
-	qq[
-max_connections = 100
-log_statement = none
-]);
-$node->start;
-$node->safe_psql('postgres', 'CREATE EXTENSION test_checksums;');
-# Create some content to have un-checksummed data in the cluster
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1, 1000000) AS a;");
-
-# Enable data checksums and wait for the state transition to 'on'
-enable_data_checksums($node, wait => 'on');
-
-$node->safe_psql('postgres', 'UPDATE t SET a = a + 1;');
-
-disable_data_checksums($node, wait => 1);
-
-$node->append_conf('postgresql.conf', 'full_page_writes = off');
-$node->restart;
-test_checksum_state($node, 'off');
-
-$node->safe_psql('postgres', 'UPDATE t SET a = a + 1;');
-$node->safe_psql('postgres', 'DELETE FROM t WHERE a < 10000;');
-
-$node->adjust_conf('postgresql.conf', 'full_page_writes', 'on');
-$node->restart;
-test_checksum_state($node, 'off');
-
-enable_data_checksums($node, wait => 'on');
-
-my $result = $node->safe_psql('postgres', 'SELECT count(*) FROM t;');
-is($result, '990003', 'Reading back all data from table t');
-
-$node->stop;
-my $log = PostgreSQL::Test::Utils::slurp_file($node->logfile, 0);
-unlike(
-	$log,
-	qr/page verification failed,.+\d$/m,
-	"no checksum validation errors in server log");
-
-done_testing();
diff --git a/src/test/modules/test_checksums/t/010_backup_straddle.pl b/src/test/modules/test_checksums/t/010_backup_straddle.pl
deleted file mode 100644
index aeeb3c8ccb0..00000000000
--- a/src/test/modules/test_checksums/t/010_backup_straddle.pl
+++ /dev/null
@@ -1,260 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test base backups running while the data checksum state changes.  The
-# transition to "on" happens before the checkpoint which flushes the rewritten
-# pages, so a backup straddling it reads on-disk pages which legitimately lack
-# checksums and carry LSNs older than the backup start.  The same applies to
-# checksums being disabled and re-enabled while a backup runs: hint bit
-# updates made while checksums were off reach disk without a checksum update
-# and without moving the page LSN, so once the re-enabling completes the
-# backup would resume verification and misjudge those pages until the
-# rewritten versions are flushed.
-#
-# Both scenarios hold the two sides with injection points: the backup after
-# its starting checkpoint but before it sends any file data, and the enabling
-# after the state changed to "on" but before the checkpoint which flushes the
-# rewritten pages.  The backup is thus guaranteed to read the stale on-disk
-# pages after the state change, without any timing assumptions.
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use File::Path qw(rmtree);
-use Test::More;
-use IPC::Run;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# This test suite is potentially expensive due to it requiring an increased
-# shared_buffers setting.  It requires the "checksum" PG_TEST_EXTRA setting to
-# not cause false positives on slow or constrained systems.
-if ($ENV{PG_TEST_EXTRA})
-{
-	plan skip_all => 'Expensive data checksums test disabled'
-	  unless ($ENV{PG_TEST_EXTRA} =~ /\bchecksum(_extended)?\b/);
-}
-else
-{
-	plan skip_all => 'Expensive data checksums test disabled';
-}
-
-if ($ENV{enable_injection_points} ne 'yes')
-{
-	plan skip_all => 'Injection points not supported by this build';
-}
-
-my $node = PostgreSQL::Test::Cluster->new('backup_node');
-$node->init(no_data_checksums => 1, allows_streaming => 1);
-# The pages rewritten while enabling must stay dirty in shared buffers until
-# the final checkpoint, otherwise they reach disk with checksums on their own
-# and nothing is left to misjudge.  The background writer must not flush them
-# behind our back, and shared_buffers must exceed four times the table size
-# so that the scan below does not go through a ring buffer.  Autovacuum is
-# disabled so that nothing sets hint bits behind our back, and wal_log_hints
-# (implied by allows_streaming) must be off so that setting them does not
-# move the page LSNs past the backup start.
-$node->append_conf('postgresql.conf', 'shared_buffers = 32MB');
-$node->append_conf('postgresql.conf', 'bgwriter_lru_maxpages = 0');
-$node->append_conf('postgresql.conf', 'autovacuum = off');
-$node->append_conf('postgresql.conf', 'wal_log_hints = off');
-$node->start;
-
-$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
-
-# A body of relation pages for the backup to misjudge.  The scan pulls the
-# table into shared buffers so that enabling doesn't read it through a ring
-# buffer, which would write the pages back out.
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,100000) AS a;");
-$node->safe_psql('postgres', "SELECT count(*) FROM t;");
-test_checksum_state($node, 'off');
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('basebackup-before-send-files','wait');");
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('datachecksums-on-before-checkpoint','wait');"
-);
-
-my $backupdir = $node->backup_dir . '/straddle';
-my ($out, $err) = ('', '');
-my $backup = IPC::Run::start(
-	[
-		'pg_basebackup', '-D',
-		$backupdir, '--wal-method=none',
-		'--no-sync', '--checkpoint=fast',
-		'-d', $node->connstr('postgres')
-	],
-	'>',
-	\$out,
-	'2>',
-	\$err,
-	IPC::Run::timeout(180));
-
-$node->wait_for_event('walsender', 'basebackup-before-send-files');
-
-# Enable checksums while the backup is held, then release the backup once the
-# enabling has reached the "on" state and is held before its checkpoint.
-enable_data_checksums($node);
-$node->wait_for_event('datachecksums launcher',
-	'datachecksums-on-before-checkpoint');
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_wakeup('basebackup-before-send-files');");
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('basebackup-before-send-files');");
-
-ok($backup->finish, 'backup straddling enable completion succeeds')
-  or diag("stderr: $err");
-
-# The backup must not even mention checksums: it must skip verification
-# entirely, including the warning-only path for short reads.
-unlike($err, qr/checksum/, 'straddling backup does not verify checksums');
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_wakeup('datachecksums-on-before-checkpoint');");
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('datachecksums-on-before-checkpoint');");
-
-wait_for_checksum_state($node, 'on');
-$node->poll_query_until('postgres',
-		"SELECT count(*) = 0 FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums launcher';");
-
-# A backup started once enabling has completed must verify, and pass
-$node->command_ok(
-	[
-		'pg_basebackup', '-D',
-		$node->backup_dir . '/after_enable', '--wal-method=none',
-		'--no-sync', '--checkpoint=fast'
-	],
-	'backup after enable completion succeeds');
-rmtree($node->backup_dir . '/after_enable');
-
-# Now test a backup which straddles checksums being disabled and re-enabled.
-# Recreate the table since the earlier scan set its hint bits and the rewrite
-# gave the pages checksums; the new contents are not read here, leaving the
-# hint bits unset until checksums are off.
-$node->safe_psql('postgres', "DROP TABLE t;");
-$node->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,100000) AS a;");
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('basebackup-before-send-files','wait');");
-
-$backupdir = $node->backup_dir . '/onoffon';
-($out, $err) = ('', '');
-$backup = IPC::Run::start(
-	[
-		'pg_basebackup', '-D',
-		$backupdir, '--wal-method=none',
-		'--no-sync', '--checkpoint=fast',
-		'-d', $node->connstr('postgres')
-	],
-	'>',
-	\$out,
-	'2>',
-	\$err,
-	IPC::Run::timeout(180));
-
-$node->wait_for_event('walsender', 'basebackup-before-send-files');
-
-disable_data_checksums($node, wait => 1);
-
-# With checksums off, the scan sets hint bits without WAL logging them, and
-# the checkpoint flushes the modified pages without updating their checksums.
-# The on-disk pages now carry stale checksums and LSNs older than the backup
-# start.
-$node->safe_psql('postgres', "SELECT count(*) FROM t;");
-$node->safe_psql('postgres', "CHECKPOINT;");
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('datachecksums-on-before-checkpoint','wait');"
-);
-
-enable_data_checksums($node);
-$node->wait_for_event('datachecksums launcher',
-	'datachecksums-on-before-checkpoint');
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_wakeup('basebackup-before-send-files');");
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('basebackup-before-send-files');");
-
-ok($backup->finish, 'backup straddling disable and re-enable succeeds')
-  or diag("stderr: $err");
-unlike($err, qr/checksum/,
-	'backup straddling disable and re-enable does not verify checksums');
-
-$node->safe_psql('postgres',
-	"SELECT injection_points_wakeup('datachecksums-on-before-checkpoint');");
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('datachecksums-on-before-checkpoint');");
-
-wait_for_checksum_state($node, 'on');
-$node->poll_query_until('postgres',
-		"SELECT count(*) = 0 FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums launcher';");
-rmtree($backupdir);
-
-# A backup started once re-enabling has completed must verify, and pass
-$node->command_ok(
-	[
-		'pg_basebackup', '-D',
-		$node->backup_dir . '/after_onoffon', '--wal-method=none',
-		'--no-sync', '--checkpoint=fast'
-	],
-	'backup after re-enable completion succeeds');
-rmtree($node->backup_dir . '/after_onoffon');
-
-# Test another backup, but this time inject synthetic checksum verification
-# failures into it.  The regex matching the WARNING is different from the next
-# test on purpose as it will have NOTICE output from the injection point as
-# well.
-$node->safe_psql('postgres',
-	"SELECT injection_points_attach('basebackup-fail-checksum-verification', 'notice');"
-);
-$node->command_checks_all(
-	[
-		'pg_basebackup', '-D',
-		$node->backup_dir . '/corrupt', '--wal-method=none',
-		'--no-sync', '--checkpoint=fast'
-	],
-	1,
-	[qr{^$}],
-	[qr/WARNING.*checksum verification failed/s],
-	'pg_basebackup reports checksum mismatch');
-rmtree($node->backup_dir . '/corrupt');
-$node->safe_psql('postgres',
-	"SELECT injection_points_detach('basebackup-fail-checksum-verification');"
-);
-
-# Now corrupt data on disk and take another backup to make sure the corruption
-# is reported.
-my $corrupt_table = $node->safe_psql('postgres',
-	q{CREATE TABLE corrupt_table AS SELECT a FROM generate_series(1,10000) AS a; ALTER TABLE corrupt_table SET (autovacuum_enabled=false); SELECT pg_relation_filepath('corrupt_table')}
-);
-
-$node->stop;
-$node->corrupt_page_checksum($corrupt_table, 0);
-$node->start;
-
-$node->command_checks_all(
-	[
-		'pg_basebackup', '-D',
-		$node->backup_dir . '/corrupt', '--wal-method=none',
-		'--no-sync', '--checkpoint=fast'
-	],
-	1,
-	[qr{^$}],
-	[qr/^WARNING.*checksum verification failed/s],
-	'pg_basebackup reports checksum mismatch');
-rmtree($node->backup_dir . '/corrupt');
-
-$node->stop;
-done_testing();
diff --git a/src/test/modules/test_checksums/t/011_standby_straddle.pl b/src/test/modules/test_checksums/t/011_standby_straddle.pl
deleted file mode 100644
index e50fb65fcaf..00000000000
--- a/src/test/modules/test_checksums/t/011_standby_straddle.pl
+++ /dev/null
@@ -1,249 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-# Test that a standby does not become available for base backups before it
-# has re-replayed the latest data checksum state change after a restart.
-#
-# When a standby replays XLOG2_CHECKSUMS it writes the new state to
-# pg_control, but the location of the change is only tracked in shared
-# memory.  If the standby restarts before a restartpoint covers the record,
-# and reaches consistency below it, base backups would resume checksum
-# verification with the change location unknown, while the pages rewritten
-# before the change may not have reached disk.  The redo routine must
-# therefore advance minRecoveryPoint to the record, so that consistency (and
-# with it hot standby and base backups) is withheld until the change location
-# is known again.
-#
-# The test holds the enabling on the primary between the state change and its
-# final checkpoint, waits for the standby to replay the state change, and
-# crashes the standby so that the rewritten pages never reach its disk.  WAL
-# from the enabling onwards is removed from the standby's pg_wal and
-# streaming is disabled, so that replay after the restart stalls below the
-# state change record.  Restarted this way, the standby must refuse
-# connections; once streaming is re-enabled and the record replayed again,
-# base backups must succeed without spurious checksum failures.
-
-use strict;
-use warnings FATAL => 'all';
-
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use File::Path qw(rmtree);
-use Test::More;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use DataChecksums::Utils;
-
-# This test suite is potentially expensive due to it requiring an increased
-# shared_buffers setting and use custom timeouts.  It requires the
-# "checksum_extended" PG_TEST_EXTRA setting to not cause false positives on
-# slow or constrained systems.
-if ($ENV{PG_TEST_EXTRA})
-{
-	plan skip_all => 'Expensive data checksums test disabled'
-	  unless ($ENV{PG_TEST_EXTRA} =~ /\bchecksum_extended\b/);
-}
-else
-{
-	plan skip_all => 'Expensive data checksums test disabled';
-}
-
-if ($ENV{enable_injection_points} ne 'yes')
-{
-	plan skip_all => 'Injection points not supported by this build';
-}
-
-my $node_primary = PostgreSQL::Test::Cluster->new('straddle_primary');
-$node_primary->init(no_data_checksums => 1, allows_streaming => 1);
-# The pages rewritten while enabling must stay dirty in shared buffers until
-# the final checkpoint, and their standby copies must stay dirty as well, so
-# that the on-disk pages legitimately lack checksums.  wal_log_hints (implied
-# by allows_streaming) is turned off to keep the page LSNs put during setup.
-$node_primary->append_conf('postgresql.conf', 'shared_buffers = 128MB');
-$node_primary->append_conf('postgresql.conf', 'autovacuum = off');
-$node_primary->append_conf('postgresql.conf', 'wal_log_hints = off');
-$node_primary->start;
-
-$node_primary->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
-
-my $slotname = 'physical_slot';
-$node_primary->safe_psql('postgres',
-	"SELECT pg_create_physical_replication_slot('$slotname');");
-
-# A body of relation pages whose standby copies will lack checksums
-$node_primary->safe_psql('postgres',
-	"CREATE TABLE t AS SELECT generate_series(1,100000) AS a;");
-
-my $backup_name = 'straddle_backup';
-$node_primary->backup($backup_name);
-
-my $node_standby = PostgreSQL::Test::Cluster->new('straddle_standby');
-$node_standby->init_from_backup($node_primary, $backup_name,
-	has_streaming => 1);
-# The background writer must not flush the replayed page rewrites behind our
-# back, or nothing is left to protect and minRecoveryPoint could move on its
-# own.
-$node_standby->append_conf(
-	'postgresql.conf', qq[
-primary_slot_name = '$slotname'
-bgwriter_lru_maxpages = 0
-]);
-$node_standby->start;
-
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-test_checksum_state($node_primary, 'off');
-test_checksum_state($node_standby, 'off');
-
-# Pin the restartpoint the later base backups will start from: replay a
-# primary checkpoint and force a restartpoint on it.  No further checkpoint
-# record reaches the standby until the enabling is released, so this remains
-# the standby's backup starting checkpoint throughout.
-$node_primary->safe_psql('postgres', 'CHECKPOINT;');
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-$node_standby->safe_psql('postgres', 'CHECKPOINT;');
-
-# Put everything the enabling writes into fresh WAL segments, so that the
-# standby's copies of them can be removed later, and remember where the
-# enabling era begins.
-$node_primary->safe_psql('postgres', 'SELECT pg_switch_wal();');
-
-# Enable checksums, holding the launcher after the state change but before
-# the final checkpoint, so the rewritten pages stay dirty everywhere.
-$node_primary->safe_psql('postgres',
-	"SELECT injection_points_attach('datachecksums-enable-checksums-delay', 'wait');"
-);
-$node_primary->safe_psql('postgres',
-	"SELECT injection_points_attach('datachecksums-on-before-checkpoint','wait');"
-);
-enable_data_checksums($node_primary);
-
-$node_primary->wait_for_event('datachecksums launcher',
-	'datachecksums-enable-checksums-delay');
-my $enable_start_lsn =
-  $node_primary->safe_psql('postgres', 'SELECT pg_current_wal_insert_lsn();');
-my $enable_start_seg = $node_primary->safe_psql('postgres',
-	"SELECT pg_walfile_name('$enable_start_lsn');");
-$node_primary->safe_psql('postgres',
-	"SELECT injection_points_wakeup('datachecksums-enable-checksums-delay');"
-);
-
-# Immediately start to wait for the next event and hold off on detaching the
-# previous injection point till later to avoid delays and risk missing the
-# wait event
-$node_primary->wait_for_event('datachecksums launcher',
-	'datachecksums-on-before-checkpoint');
-# Detach the injection point now that we have some more time
-$node_primary->safe_psql('postgres',
-	"SELECT injection_points_detach('datachecksums-enable-checksums-delay');"
-);
-
-# The standby has now replayed the state change: its pg_control says "on"
-# while the rewritten pages are only dirty in its shared buffers.
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-wait_for_checksum_state($node_standby, 'on');
-
-# Crash the standby, losing the dirty rewritten pages.
-$node_standby->stop('immediate');
-
-# The state change record must have dragged minRecoveryPoint along with it,
-# otherwise the standby can become consistent below the record after the
-# restart.
-my ($stdout, $stderr) =
-  run_command([ 'pg_controldata', $node_standby->data_dir ]);
-my ($min_recovery) =
-  $stdout =~ /Minimum recovery ending location:\s*([0-9A-F]+\/[0-9A-F]+)/;
-die "could not parse pg_controldata output" unless defined $min_recovery;
-
-my $result = $node_primary->safe_psql('postgres',
-	"SELECT '$min_recovery'::pg_lsn > '$enable_start_lsn'::pg_lsn;");
-is($result, 't', 'minRecoveryPoint advanced past the checksum state change');
-
-# Remove the enabling-era WAL from the standby and cut it off from the
-# primary, so that replay after the restart stalls below the state change.
-# The replication slot retains the removed segments on the primary.
-my $wal_dir = $node_standby->data_dir . '/pg_wal';
-opendir(my $dh, $wal_dir) or die "could not open $wal_dir: $!";
-foreach my $segment (readdir($dh))
-{
-	next unless $segment =~ /^[0-9A-F]{24}$/;
-	next unless $segment ge $enable_start_seg;
-	unlink("$wal_dir/$segment")
-	  or die "could not unlink $wal_dir/$segment: $!";
-}
-closedir($dh);
-$node_standby->append_conf('postgresql.conf', "primary_conninfo = ''");
-
-# The standby must not reach consistency until it has re-replayed the state
-# change, so startup must not complete within the timeout.  Reaching hot
-# standby below the record would make pg_ctl return success here.
-my $started;
-{
-	local $ENV{PGCTLTIMEOUT} = 10;
-	$started = $node_standby->start(fail_ok => 1);
-}
-is($started, 0,
-	'standby withholds consistency until the state change is replayed again');
-
-my ($ret, $out, $err) = $node_standby->psql('postgres', 'SELECT 1;');
-isnt($ret, 0, 'standby refuses connections while below the state change');
-
-# Reconnect the standby; streaming provides the removed WAL again, replay
-# passes the state change and the standby becomes consistent.
-$node_standby->enable_streaming($node_primary);
-$node_standby->reload;
-$node_standby->poll_query_until('postgres', 'SELECT true;');
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-
-# The rewritten pages are again only dirty in shared buffers, so the on-disk
-# pages still lack checksums.  A base backup must skip verification entirely
-# and pass without mentioning checksums on stderr.  Standby backups always
-# print a NOTICE about WAL archiving, so stderr is not empty.
-$node_standby->command_checks_all(
-	[
-		'pg_basebackup', '-D',
-		$node_standby->backup_dir . '/underway', '--wal-method=none',
-		'--no-sync', '--checkpoint=fast'
-	],
-	0,
-	[qr{^$}],
-	[qr{^(?!.*checksum)}s],
-	'backup from standby while enabling is underway succeeds');
-rmtree($node_standby->backup_dir . '/underway');
-
-# Release the enabling; its final checkpoint flushes the rewritten pages.
-$node_primary->safe_psql('postgres',
-	"SELECT injection_points_wakeup('datachecksums-on-before-checkpoint');");
-$node_primary->safe_psql('postgres',
-	"SELECT injection_points_detach('datachecksums-on-before-checkpoint');");
-wait_for_checksum_state($node_primary, 'on');
-$node_primary->poll_query_until('postgres',
-		"SELECT count(*) = 0 FROM pg_catalog.pg_stat_activity "
-	  . "WHERE backend_type = 'datachecksums launcher';");
-
-# A restartpoint on the final checkpoint lets verification resume, and a
-# backup started from it must again pass.
-$node_primary->wait_for_catchup($node_standby, 'replay',
-	$node_primary->lsn('insert'));
-$node_standby->safe_psql('postgres', 'CHECKPOINT;');
-
-$node_standby->command_checks_all(
-	[
-		'pg_basebackup', '-D',
-		$node_standby->backup_dir . '/after_enable', '--wal-method=none',
-		'--no-sync', '--checkpoint=fast'
-	],
-	0,
-	[qr{^$}],
-	[qr{^(?!.*checksum)}s],
-	'backup from standby after enable completion succeeds');
-rmtree($node_standby->backup_dir . '/after_enable');
-
-$node_standby->stop;
-$node_primary->stop;
-done_testing();
diff --git a/src/test/modules/test_checksums/t/DataChecksums/Utils.pm b/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
deleted file mode 100644
index 3aa533d777f..00000000000
--- a/src/test/modules/test_checksums/t/DataChecksums/Utils.pm
+++ /dev/null
@@ -1,243 +0,0 @@
-
-# Copyright (c) 2026, PostgreSQL Global Development Group
-
-=pod
-
-=head1 NAME
-
-DataChecksums::Utils - Utility functions for testing data checksums in a running cluster
-
-=head1 SYNOPSIS
-
-  use PostgreSQL::Test::Cluster;
-  use DataChecksums::Utils qw( .. );
-
-  # Create, and start, a new cluster
-  my $node = PostgreSQL::Test::Cluster->new('primary');
-  $node->init;
-  $node->start;
-
-  test_checksum_state($node, 'off');
-
-  enable_data_checksums($node);
-
-  wait_for_checksum_state($node, 'on');
-
-
-=cut
-
-package DataChecksums::Utils;
-
-use strict;
-use warnings FATAL => 'all';
-use Exporter 'import';
-use PostgreSQL::Test::Cluster;
-use PostgreSQL::Test::Utils;
-use Test::More;
-
-our @EXPORT = qw(
-  cointoss
-  disable_data_checksums
-  enable_data_checksums
-  random_sleep
-  stopmode
-  test_checksum_state
-  wait_for_checksum_state
-);
-
-=pod
-
-=head1 METHODS
-
-=over
-
-=item test_checksum_state(node, state)
-
-Test that the current value of the data checksum GUC in the server running
-at B<node> matches B<state>.  If the values differ, a test failure is logged.
-Returns True if the values match, otherwise False.
-
-=cut
-
-sub test_checksum_state
-{
-	my ($postgresnode, $state) = @_;
-
-	my $result = $postgresnode->safe_psql('postgres',
-		"SELECT setting FROM pg_catalog.pg_settings WHERE name = 'data_checksums';"
-	);
-	is($result, $state,
-			'ensure checksums are set to '
-		  . $state . ' on '
-		  . $postgresnode->name());
-	return $result eq $state;
-}
-
-=item wait_for_checksum_state(node, state)
-
-Test the value of the data checksum GUC in the server running at B<node>
-repeatedly until it matches B<state> or times out.  Processing will run for
-$PostgreSQL::Test::Utils::timeout_default seconds before timing out.  If the
-values differ when the process times out, False is returned and a test failure
-is logged, otherwise True.
-
-=cut
-
-sub wait_for_checksum_state
-{
-	my ($postgresnode, $state) = @_;
-
-	my $res = $postgresnode->poll_query_until(
-		'postgres',
-		"SELECT setting FROM pg_catalog.pg_settings WHERE name = 'data_checksums';",
-		$state);
-	is($res, 1,
-			'ensure data checksums are transitioned to '
-		  . $state . ' on '
-		  . $postgresnode->name());
-	return $res == 1;
-}
-
-=item enable_data_checksums($node, %params)
-
-Function for enabling data checksums in the cluster running at B<node>.
-
-=over
-
-=item cost_delay
-
-The B<cost_delay> to use when enabling data checksums, default is 0.
-
-=item cost_limit
-
-The B<cost_limit> to use when enabling data checksums, default is 100.
-
-=item wait
-
-If defined, the function will wait for the state defined in this parameter,
-waiting timing out, before returning.  The function will wait for
-$PostgreSQL::Test::Utils::timeout_default seconds before timing out.
-
-=back
-
-=cut
-
-sub enable_data_checksums
-{
-	my $postgresnode = shift;
-	my %params = @_;
-
-	# Set sane defaults for the parameters
-	$params{cost_delay} = 0 unless (defined($params{cost_delay}));
-	$params{cost_limit} = 100 unless (defined($params{cost_limit}));
-
-	my $query = <<'EOQ';
-SELECT pg_enable_data_checksums(%s, %s);
-EOQ
-
-	$postgresnode->safe_psql('postgres',
-		sprintf($query, $params{cost_delay}, $params{cost_limit}));
-
-	if (defined($params{wait}))
-	{
-		wait_for_checksum_state($postgresnode, $params{wait});
-		# If we are tasked with waiting for an end state, also wait for the
-		# launcher to exit.
-		if ($params{wait} eq 'on' || $params{wait} eq 'off')
-		{
-			$postgresnode->poll_query_until('postgres',
-					"SELECT count(*) = 0 "
-				  . "FROM pg_catalog.pg_stat_activity "
-				  . "WHERE backend_type = 'datachecksums launcher';");
-		}
-	}
-}
-
-=item disable_data_checksums($node, %params)
-
-Function for disabling data checksums in the cluster running at B<node>.
-
-=over
-
-=item wait
-
-If defined, the function will wait for the state to turn to B<off>, or
-waiting timing out, before returning.  The function will wait for
-$PostgreSQL::Test::Utils::timeout_default seconds before timing out.
-Unlike in C<enable_data_checksums> the value of the parameter is discarded.
-
-=back
-
-=cut
-
-sub disable_data_checksums
-{
-	my $postgresnode = shift;
-	my %params = @_;
-
-	$postgresnode->safe_psql('postgres',
-		'SELECT pg_disable_data_checksums();');
-
-	if (defined($params{wait}))
-	{
-		wait_for_checksum_state($postgresnode, 'off');
-		$postgresnode->poll_query_until('postgres',
-				"SELECT count(*) = 0 "
-			  . "FROM pg_catalog.pg_stat_activity "
-			  . "WHERE backend_type = 'datachecksums launcher';");
-	}
-}
-
-=item cointoss
-
-Helper for retrieving a binary value with random distribution for deciding
-whether to turn things off during testing.
-
-=back
-
-=cut
-
-sub cointoss
-{
-	return int(rand() < 0.5);
-}
-
-=item random_sleep(max)
-
-Helper for injecting random sleeps here and there in the testrun. The sleep
-duration will be in the range (0,B<max>), but won't be predictable in order to
-avoid sleep patterns that manage to avoid race conditions and timing bugs.
-The default B<max> is 3 seconds.
-
-=back
-
-=cut
-
-sub random_sleep
-{
-	my $max = shift;
-	return if (defined($max) && ($max == 0));
-	sleep(int(rand(defined($max) ? $max : 3))) if cointoss;
-}
-
-=item stopmode
-
-Small helper function for randomly selecting a valid stopmode.
-
-=back
-
-=cut
-
-sub stopmode
-{
-	return 'immediate' if (cointoss);
-	return 'fast';
-}
-
-=pod
-
-=back
-
-=cut
-
-1;
diff --git a/src/test/modules/test_checksums/test_checksums--1.0.sql b/src/test/modules/test_checksums/test_checksums--1.0.sql
deleted file mode 100644
index c674fee02bb..00000000000
--- a/src/test/modules/test_checksums/test_checksums--1.0.sql
+++ /dev/null
@@ -1,16 +0,0 @@
-/* src/test/modules/test_checksums/test_checksums--1.0.sql */
-
--- complain if script is sourced in psql, rather than via CREATE EXTENSION
-\echo Use "CREATE EXTENSION test_checksums" to load this file. \quit
-
-CREATE FUNCTION dcw_inject_delay_barrier(attach boolean DEFAULT true)
-	RETURNS pg_catalog.void
-	AS 'MODULE_PATHNAME' LANGUAGE C;
-
-CREATE FUNCTION dcw_inject_launcher_delay(attach boolean DEFAULT true)
-	RETURNS pg_catalog.void
-	AS 'MODULE_PATHNAME' LANGUAGE C;
-
-CREATE FUNCTION dcw_inject_startup_delay(attach boolean DEFAULT true)
-	RETURNS pg_catalog.void
-	AS 'MODULE_PATHNAME' LANGUAGE C;
diff --git a/src/test/modules/test_checksums/test_checksums.c b/src/test/modules/test_checksums/test_checksums.c
deleted file mode 100644
index 621cf788dad..00000000000
--- a/src/test/modules/test_checksums/test_checksums.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*--------------------------------------------------------------------------
- *
- * test_checksums.c
- *		Test data checksums
- *
- * Copyright (c) 2026, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- *		src/test/modules/test_checksums/test_checksums.c
- *
- * -------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "funcapi.h"
-#include "miscadmin.h"
-#include "postmaster/datachecksum_state.h"
-#include "storage/latch.h"
-#include "utils/injection_point.h"
-#include "utils/wait_event.h"
-
-PG_MODULE_MAGIC;
-
-extern PGDLLEXPORT void dc_delay_barrier(const char *name, const void *private_data, void *arg);
-
-/*
- * Test for delaying emission of procsignalbarriers.
- */
-void
-dc_delay_barrier(const char *name, const void *private_data, void *arg)
-{
-	(void) name;
-	(void) private_data;
-
-	(void) WaitLatch(MyLatch,
-					 WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
-					 (3 * 1000),
-					 WAIT_EVENT_PG_SLEEP);
-}
-
-PG_FUNCTION_INFO_V1(dcw_inject_delay_barrier);
-Datum
-dcw_inject_delay_barrier(PG_FUNCTION_ARGS)
-{
-#ifdef USE_INJECTION_POINTS
-	bool		attach = PG_GETARG_BOOL(0);
-
-	if (attach)
-		InjectionPointAttach("datachecksums-enable-checksums-delay",
-							 "test_checksums",
-							 "dc_delay_barrier",
-							 NULL,
-							 0);
-	else
-		InjectionPointDetach("datachecksums-enable-checksums-delay");
-#else
-	elog(ERROR,
-		 "test is not working as intended when injection points are disabled");
-#endif
-	PG_RETURN_VOID();
-}
-
-PG_FUNCTION_INFO_V1(dcw_inject_launcher_delay);
-Datum
-dcw_inject_launcher_delay(PG_FUNCTION_ARGS)
-{
-#ifdef USE_INJECTION_POINTS
-	bool		attach = PG_GETARG_BOOL(0);
-
-	if (attach)
-		InjectionPointAttach("datachecksumsworker-launcher-delay",
-							 "test_checksums",
-							 "dc_delay_barrier",
-							 NULL,
-							 0);
-	else
-		InjectionPointDetach("datachecksumsworker-launcher-delay");
-#else
-	elog(ERROR,
-		 "test is not working as intended when injection points are disabled");
-#endif
-	PG_RETURN_VOID();
-}
-
-PG_FUNCTION_INFO_V1(dcw_inject_startup_delay);
-Datum
-dcw_inject_startup_delay(PG_FUNCTION_ARGS)
-{
-#ifdef USE_INJECTION_POINTS
-	bool		attach = PG_GETARG_BOOL(0);
-
-	if (attach)
-		InjectionPointAttach("datachecksumsworker-startup-delay",
-							 "test_checksums",
-							 "dc_delay_barrier",
-							 NULL,
-							 0);
-	else
-		InjectionPointDetach("datachecksumsworker-startup-delay");
-#else
-	elog(ERROR,
-		 "test is not working as intended when injection points are disabled");
-#endif
-	PG_RETURN_VOID();
-}
diff --git a/src/test/modules/test_checksums/test_checksums.control b/src/test/modules/test_checksums/test_checksums.control
deleted file mode 100644
index 84b4cc035a7..00000000000
--- a/src/test/modules/test_checksums/test_checksums.control
+++ /dev/null
@@ -1,4 +0,0 @@
-comment = 'Test code for data checksums'
-default_version = '1.0'
-module_pathname = '$libdir/test_checksums'
-relocatable = true
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index dd4502923b1..49cc575a12d 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2100,44 +2100,6 @@ pg_stat_progress_create_index| SELECT s.pid,
     s.param15 AS partitions_done
    FROM (pg_stat_get_progress_info('CREATE INDEX'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
-pg_stat_progress_data_checksums| SELECT s.pid,
-    s.datid,
-    d.datname,
-        CASE s.param1
-            WHEN 0 THEN 'enabling'::text
-            WHEN 1 THEN 'disabling'::text
-            WHEN 2 THEN 'waiting on temporary tables'::text
-            WHEN 3 THEN 'waiting on barrier'::text
-            WHEN 4 THEN 'done'::text
-            ELSE NULL::text
-        END AS phase,
-        CASE s.param2
-            WHEN '-1'::integer THEN NULL::bigint
-            ELSE s.param2
-        END AS databases_total,
-        CASE s.param3
-            WHEN '-1'::integer THEN NULL::bigint
-            ELSE s.param3
-        END AS databases_done,
-        CASE s.param4
-            WHEN '-1'::integer THEN NULL::bigint
-            ELSE s.param4
-        END AS relations_total,
-        CASE s.param5
-            WHEN '-1'::integer THEN NULL::bigint
-            ELSE s.param5
-        END AS relations_done,
-        CASE s.param6
-            WHEN '-1'::integer THEN NULL::bigint
-            ELSE s.param6
-        END AS blocks_total,
-        CASE s.param7
-            WHEN '-1'::integer THEN NULL::bigint
-            ELSE s.param7
-        END AS blocks_done
-   FROM (pg_stat_get_progress_info('DATACHECKSUMS'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
-     LEFT JOIN pg_database d ON ((s.datid = d.oid)))
-  ORDER BY s.datid;
 pg_stat_progress_repack| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index eb11aacfe5a..7dcd678259b 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -51,15 +51,6 @@ client backend|relation|vacuum
 client backend|temp relation|normal
 client backend|wal|init
 client backend|wal|normal
-datachecksums launcher|relation|bulkread
-datachecksums launcher|relation|normal
-datachecksums launcher|wal|init
-datachecksums launcher|wal|normal
-datachecksums worker|relation|bulkread
-datachecksums worker|relation|normal
-datachecksums worker|relation|vacuum
-datachecksums worker|wal|init
-datachecksums worker|wal|normal
 io worker|relation|bulkread
 io worker|relation|bulkwrite
 io worker|relation|init
@@ -104,7 +95,7 @@ walsummarizer|wal|init
 walsummarizer|wal|normal
 walwriter|wal|init
 walwriter|wal|normal
-(88 rows)
+(79 rows)
 \a
 -- ensure that both seqscan and indexscan plans are allowed
 SET enable_seqscan TO on;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index bcf981a02a2..9d499c5665b 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -438,7 +438,6 @@ CheckPointStmt
 CheckpointStatsData
 CheckpointerRequest
 CheckpointerShmemStruct
-ChecksumBarrierCondition
 ChecksumStateType
 Chromosome
 CkptSortItem
@@ -632,10 +631,6 @@ DSMRegistryCtxStruct
 DSMRegistryEntry
 DWORD
 DWORD64
-DataChecksumsStateStruct
-DataChecksumsWorkerDatabase
-DataChecksumsWorkerOperation
-DataChecksumsWorkerResult
 DataDirSyncMethod
 DataDumperPtr
 DataPageDeleteStack
@@ -4478,7 +4473,6 @@ xl_btree_unlink_page
 xl_btree_update
 xl_btree_vacuum
 xl_checkpoint_redo
-xl_checksum_state
 xl_clog_truncate
 xl_commit_ts_truncate
 xl_dbase_create_file_copy_rec
-- 
2.39.3 (Apple Git-146)

