0001-add-fast-parameter-to-enable-disable-checksums.patch
text/x-patch
Filename: 0001-add-fast-parameter-to-enable-disable-checksums.patch
Type: text/x-patch
Part: 0
From 4eba7bbb739f5e7b95c4909d1cee2a437d8c6eb3 Mon Sep 17 00:00:00 2001
From: test <test>
Date: Sun, 3 May 2026 00:40:17 +0200
Subject: [PATCH 1/2] add fast parameter to enable/disable checksums
XXX Should this default to true or false? Most production systems would
probably want 'false' to reduce impact, but PG19 does fast checkpoints
by default.
---
doc/src/sgml/func/func-admin.sgml | 14 ++++++++++--
src/backend/access/transam/xlog.c | 23 ++++++++++++++------
src/backend/postmaster/datachecksum_state.c | 24 +++++++++++++++------
src/include/access/xlog.h | 4 ++--
src/include/catalog/pg_proc.dat | 11 +++++-----
src/include/postmaster/datachecksum_state.h | 3 ++-
6 files changed, 56 insertions(+), 23 deletions(-)
diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml
index 24ecb46542e..06360ea1b95 100644
--- a/doc/src/sgml/func/func-admin.sgml
+++ b/doc/src/sgml/func/func-admin.sgml
@@ -3158,7 +3158,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<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> )
+ <function>pg_enable_data_checksums</function> ( <optional><parameter>cost_delay</parameter> <type>int</type>, <parameter>cost_limit</parameter> <type>int</type></optional>, <parameter>fast</parameter> <type>bool</type></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3175,6 +3175,11 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
specified, the process is throttled using the same principles as
<link linkend="runtime-config-resource-vacuum-cost">Cost-based Vacuum Delay</link>.
</para>
+ <para>
+ If <parameter>fast</parameter> is specified as <literal>true</literal>
+ then a fast checkpoint will be issued when data checksums have been
+ enabled, which may cause a spike in I/O.
+ </para>
</entry>
</row>
@@ -3183,7 +3188,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
<indexterm>
<primary>pg_disable_data_checksums</primary>
</indexterm>
- <function>pg_disable_data_checksums</function> ()
+ <function>pg_disable_data_checksums</function> ( <optional><parameter>fast</parameter> <type>bool</type></optional> )
<returnvalue>void</returnvalue>
</para>
<para>
@@ -3193,6 +3198,11 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
stopped validating data checksums, the data checksum state will be
set to <literal>off</literal>.
</para>
+ <para>
+ If <parameter>fast</parameter> is specified as <literal>true</literal>
+ then a fast checkpoint will be issued when data checksums have been
+ enabled, which may cause a spike in I/O.
+ </para>
</entry>
</row>
</tbody>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 18d5dee06e0..6b8b48fa4ce 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4803,9 +4803,10 @@ SetDataChecksumsOnInProgress(void)
* state transition.
*/
void
-SetDataChecksumsOn(void)
+SetDataChecksumsOn(bool fast)
{
uint64 barrier;
+ int flags;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4820,7 +4821,7 @@ SetDataChecksumsOn(void)
SpinLockRelease(&XLogCtl->info_lck);
elog(WARNING,
"cannot set data checksums to \"on\", current state is not \"inprogress-on\", disabling");
- SetDataChecksumsOff();
+ SetDataChecksumsOff(fast);
return;
}
@@ -4850,7 +4851,11 @@ SetDataChecksumsOn(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
+
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
@@ -4868,9 +4873,15 @@ SetDataChecksumsOn(void)
* state transition.
*/
void
-SetDataChecksumsOff(void)
+SetDataChecksumsOff(bool fast)
{
uint64 barrier;
+ int flags;
+
+ /* determine flags for the checkpoint(s) */
+ flags = CHECKPOINT_FORCE | CHECKPOINT_WAIT;
+ if (fast)
+ flags |= CHECKPOINT_FAST;
SpinLockAcquire(&XLogCtl->info_lck);
@@ -4912,7 +4923,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
/*
@@ -4950,7 +4961,7 @@ SetDataChecksumsOff(void)
MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
END_CRIT_SECTION();
- RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | CHECKPOINT_FAST);
+ RequestCheckpoint(flags);
WaitForProcSignalBarrier(barrier);
}
diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c
index d0d6acdd6a2..286096217d9 100644
--- a/src/backend/postmaster/datachecksum_state.c
+++ b/src/backend/postmaster/datachecksum_state.c
@@ -291,6 +291,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation launch_operation;
int launch_cost_delay;
int launch_cost_limit;
+ bool launch_fast_checkpoint;
/*
* Is a launcher process currently running? This is set by the main
@@ -318,6 +319,7 @@ typedef struct DataChecksumsStateStruct
DataChecksumsWorkerOperation operation;
int cost_delay;
int cost_limit;
+ bool fast_checkpoint;
/*
* Signaling between the launcher and the worker process.
@@ -509,6 +511,8 @@ AbsorbDataChecksumsBarrier(ProcSignalBarrierType barrier)
Datum
disable_data_checksums(PG_FUNCTION_ARGS)
{
+ bool fast = PG_GETARG_BOOL(0);
+
PreventCommandDuringRecovery("pg_disable_data_checksums()");
if (!superuser())
@@ -516,7 +520,7 @@ disable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change data checksum state"));
- StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0);
+ StartDataChecksumsWorkerLauncher(DISABLE_DATACHECKSUMS, 0, 0, fast);
PG_RETURN_VOID();
}
@@ -530,6 +534,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
{
int cost_delay = PG_GETARG_INT32(0);
int cost_limit = PG_GETARG_INT32(1);
+ bool fast = PG_GETARG_BOOL(2);
PreventCommandDuringRecovery("pg_enable_data_checksums()");
@@ -548,7 +553,7 @@ enable_data_checksums(PG_FUNCTION_ARGS)
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cost limit must be greater than zero"));
- StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit);
+ StartDataChecksumsWorkerLauncher(ENABLE_DATACHECKSUMS, cost_delay, cost_limit, fast);
PG_RETURN_VOID();
}
@@ -568,7 +573,8 @@ enable_data_checksums(PG_FUNCTION_ARGS)
void
StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit)
+ int cost_limit,
+ bool fast)
{
BackgroundWorker bgw;
BackgroundWorkerHandle *bgw_handle;
@@ -588,6 +594,7 @@ StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
DataChecksumState->launch_operation = op;
DataChecksumState->launch_cost_delay = cost_delay;
DataChecksumState->launch_cost_limit = cost_limit;
+ DataChecksumState->launch_fast_checkpoint = fast;
/* Is the launcher already running? If so, what is it doing? */
running = DataChecksumState->launcher_running;
@@ -938,7 +945,7 @@ launcher_exit(int code, Datum arg)
* the state to off since processing cannot be resumed.
*/
if (DataChecksumsInProgressOn())
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
launcher_running = false;
@@ -1081,6 +1088,7 @@ DataChecksumsWorkerLauncherMain(Datum arg)
DataChecksumState->operation = operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
/*
@@ -1139,7 +1147,7 @@ again:
* Data checksums have been set on all pages, set the state to on in
* order to instruct backends to validate checksums on reading.
*/
- SetDataChecksumsOn();
+ SetDataChecksumsOn(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now enabled"));
@@ -1151,7 +1159,7 @@ again:
pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_PHASE,
PROGRESS_DATACHECKSUMS_PHASE_DISABLING);
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(LOG,
errmsg("data checksums are now disabled"));
}
@@ -1179,6 +1187,7 @@ done:
operation = DataChecksumState->launch_operation;
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
LWLockRelease(DataChecksumsWorkerLock);
goto again;
}
@@ -1268,7 +1277,7 @@ ProcessAllDatabases(void)
* Disable checksums on cluster, because we failed one of the
* databases and this is an all or nothing process.
*/
- SetDataChecksumsOff();
+ SetDataChecksumsOff(DataChecksumState->fast_checkpoint);
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("data checksums failed to get enabled in all databases, aborting"),
@@ -1606,6 +1615,7 @@ DataChecksumsWorkerMain(Datum arg)
DataChecksumState->cost_delay = DataChecksumState->launch_cost_delay;
DataChecksumState->cost_limit = DataChecksumState->launch_cost_limit;
+ DataChecksumState->fast_checkpoint = DataChecksumState->launch_fast_checkpoint;
}
else
costs_updated = false;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4dd98624204..8a9e8961a6a 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -253,8 +253,8 @@ 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 void SetDataChecksumsOn(bool fast);
+extern void SetDataChecksumsOff(bool fast);
extern const char *show_data_checksums(void);
extern const char *get_checksum_state_string(uint32 state);
extern void InitLocalDataChecksumState(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fa9ae79082b..fed5fba4c0c 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12457,14 +12457,15 @@
{ oid => '9258',
descr => 'disable data checksums',
proname => 'pg_disable_data_checksums', provolatile => 'v', prorettype => 'void',
- proparallel => 'r', prosrc => 'disable_data_checksums', proargtypes => '',
- proacl => '{POSTGRES=X}'},
+ proparallel => 'r', prosrc => 'disable_data_checksums', proargtypes => 'bool',
+ proallargtypes => '{bool}', proargmodes => '{i}', proargnames => '{fast}',
+ proargdefaults => '{true}', proacl => '{POSTGRES=X}'},
{ oid => '9257',
descr => 'enable data checksums',
proname => 'pg_enable_data_checksums', provolatile => 'v', prorettype => 'void',
- proparallel => 'r', proargtypes => 'int4 int4', proallargtypes => '{int4,int4}',
- proargmodes => '{i,i}', proargnames => '{cost_delay,cost_limit}',
- proargdefaults => '{0,100}', prosrc => 'enable_data_checksums',
+ proparallel => 'r', proargtypes => 'int4 int4 bool', proallargtypes => '{int4,int4,bool}',
+ proargmodes => '{i,i,i}', proargnames => '{cost_delay,cost_limit,fast}',
+ proargdefaults => '{0,100,true}', prosrc => 'enable_data_checksums',
proacl => '{POSTGRES=X}'},
# collation management functions
diff --git a/src/include/postmaster/datachecksum_state.h b/src/include/postmaster/datachecksum_state.h
index 2a1ae10d55d..6bd975c0670 100644
--- a/src/include/postmaster/datachecksum_state.h
+++ b/src/include/postmaster/datachecksum_state.h
@@ -45,7 +45,8 @@ void EmitAndWaitDataChecksumsBarrier(uint32 state);
/* Start the background processes for enabling or disabling checksums */
void StartDataChecksumsWorkerLauncher(DataChecksumsWorkerOperation op,
int cost_delay,
- int cost_limit);
+ int cost_limit,
+ bool fast);
/* Background worker entrypoints */
void DataChecksumsWorkerLauncherMain(Datum arg);
--
2.54.0