From 915e1594439328d47a04096c9811dd43a4526efe Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Sat, 13 Apr 2024 21:42:33 -0500
Subject: [PATCH v2 4/4] Reintroduce autovacuum_max_workers as a PGC_SIGHUP
 parameter.

---
 doc/src/sgml/config.sgml                      | 24 +++++++++++++++++--
 doc/src/sgml/maintenance.sgml                 |  4 ++--
 src/backend/postmaster/autovacuum.c           |  4 +++-
 src/backend/utils/misc/guc_tables.c           | 15 +++++++++---
 src/backend/utils/misc/postgresql.conf.sample |  3 ++-
 src/include/postmaster/autovacuum.h           |  1 +
 .../xid_wraparound/t/001_emergency_vacuum.pl  |  2 +-
 .../xid_wraparound/t/003_wraparounds.pl       |  2 +-
 8 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index b4d67a93b6..0f022a8056 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1914,7 +1914,7 @@ include_dir 'conf.d'
        </para>
        <para>
         Note that when autovacuum runs, up to
-        <xref linkend="guc-autovacuum-max-worker-slots"/> times this memory
+        <xref linkend="guc-autovacuum-max-workers"/> times this memory
         may be allocated, so be careful not to set the default value
         too high.  It may be useful to control for this by separately
         setting <xref linkend="guc-autovacuum-work-mem"/>.
@@ -8540,11 +8540,31 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
        <primary><varname>autovacuum_max_worker_slots</varname> configuration parameter</primary>
       </indexterm>
       </term>
+      <listitem>
+       <para>
+        Specifies the number of backend slots to reserve for autovacuum worker
+        processes.  The default is 32.  This parameter can only be set at server
+        start.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="guc-autovacuum-max-workers" xreflabel="autovacuum_max_workers">
+      <term><varname>autovacuum_max_workers</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>autovacuum_max_workers</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
       <listitem>
        <para>
         Specifies the maximum number of autovacuum processes (other than the
         autovacuum launcher) that may be running at any one time.  The default
-        is three.  This parameter can only be set at server start.
+        is three.  This parameter can only be set in the
+        <filename>postgresql.conf</filename> file or on the server command line.
+       </para>
+       <para>
+        Note that this value is silently capped to the value of
+        <xref linkend="guc-autovacuum-max-worker-slots"/>.
        </para>
       </listitem>
      </varlistentry>
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 5373acba41..0be90bdc7e 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -864,9 +864,9 @@ HINT:  Execute a database-wide VACUUM in that database.
     seconds.  (Therefore, if the installation has <replaceable>N</replaceable> databases,
     a new worker will be launched every
     <varname>autovacuum_naptime</varname>/<replaceable>N</replaceable> seconds.)
-    A maximum of <xref linkend="guc-autovacuum-max-worker-slots"/> worker processes
+    A maximum of <xref linkend="guc-autovacuum-max-workers"/> worker processes
     are allowed to run at the same time. If there are more than
-    <varname>autovacuum_max_worker_slots</varname> databases to be processed,
+    <varname>autovacuum_max_workers</varname> databases to be processed,
     the next database will be processed as soon as the first worker finishes.
     Each worker process will check each table within its database and
     execute <command>VACUUM</command> and/or <command>ANALYZE</command> as needed.
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f80365faff..ed7e2b462f 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -115,6 +115,7 @@
  */
 bool		autovacuum_start_daemon = false;
 int			autovacuum_max_worker_slots;
+int			autovacuum_max_workers;
 int			autovacuum_work_mem = -1;
 int			autovacuum_naptime;
 int			autovacuum_vac_thresh;
@@ -3346,6 +3347,7 @@ static bool
 av_worker_available(void)
 {
 	const dclist_head *freelist = &AutoVacuumShmem->av_freeWorkers;
+	int			reserved_slots = autovacuum_max_worker_slots - autovacuum_max_workers;
 
-	return dclist_count(freelist) > 0;
+	return dclist_count(freelist) > Max(0, reserved_slots);
 }
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 92dea7061a..92d4d10fe9 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3403,13 +3403,22 @@ struct config_int ConfigureNamesInt[] =
 	{
 		/* see max_connections */
 		{"autovacuum_max_worker_slots", PGC_POSTMASTER, AUTOVACUUM,
-			gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
-			NULL
+			gettext_noop("Sets the number of backend slots to allocate for autovacuum workers."),
+			gettext_noop("autovacuum_max_workers is silently capped to this value.")
 		},
 		&autovacuum_max_worker_slots,
-		3, 1, MAX_BACKENDS,
+		32, 1, MAX_BACKENDS,
 		check_autovacuum_max_worker_slots, NULL, NULL
 	},
+	{
+		{"autovacuum_max_workers", PGC_SIGHUP, AUTOVACUUM,
+			gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
+			gettext_noop("This value is silently capped to autovacuum_max_worker_slots.")
+		},
+		&autovacuum_max_workers,
+		3, 1, MAX_BACKENDS,
+		NULL, NULL, NULL
+	},
 
 	{
 		{"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index c37767cecf..c46d245153 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -658,8 +658,9 @@
 
 #autovacuum = on			# Enable autovacuum subprocess?  'on'
 					# requires track_counts to also be on.
-#autovacuum_max_worker_slots = 3	# max number of autovacuum subprocesses
+autovacuum_max_worker_slots = 32	# autovacuum worker slots to allocate
 					# (change requires restart)
+#autovacuum_max_workers = 3		# max number of autovacuum subprocesses
 #autovacuum_naptime = 1min		# time between autovacuum runs
 #autovacuum_vacuum_threshold = 50	# min number of row updates before
 					# vacuum
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index 754d04485d..598782fd34 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -29,6 +29,7 @@ typedef enum
 /* GUC variables */
 extern PGDLLIMPORT bool autovacuum_start_daemon;
 extern PGDLLIMPORT int autovacuum_max_worker_slots;
+extern PGDLLIMPORT int autovacuum_max_workers;
 extern PGDLLIMPORT int autovacuum_work_mem;
 extern PGDLLIMPORT int autovacuum_naptime;
 extern PGDLLIMPORT int autovacuum_vac_thresh;
diff --git a/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl b/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl
index f9cdd50c19..37550b67a4 100644
--- a/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl
+++ b/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl
@@ -21,7 +21,7 @@ $node->append_conf(
 autovacuum = off # run autovacuum only when to anti wraparound
 autovacuum_naptime = 1s
 # so it's easier to verify the order of operations
-autovacuum_max_worker_slots = 1
+autovacuum_max_workers = 1
 log_autovacuum_min_duration = 0
 ]);
 $node->start;
diff --git a/src/test/modules/xid_wraparound/t/003_wraparounds.pl b/src/test/modules/xid_wraparound/t/003_wraparounds.pl
index 99f76229d5..88063b4b52 100644
--- a/src/test/modules/xid_wraparound/t/003_wraparounds.pl
+++ b/src/test/modules/xid_wraparound/t/003_wraparounds.pl
@@ -24,7 +24,7 @@ $node->append_conf(
 autovacuum = off # run autovacuum only when to anti wraparound
 autovacuum_naptime = 1s
 # so it's easier to verify the order of operations
-autovacuum_max_worker_slots = 1
+autovacuum_max_workers = 1
 log_autovacuum_min_duration = 0
 ]);
 $node->start;
-- 
2.25.1

