Skip to content

Commit 6e2775e

Browse files
committed
Add new GUC reserved_connections.
This provides a way to reserve connection slots for non-superusers. The slots reserved via the new GUC are available only to users who have the new predefined role pg_use_reserved_connections. superuser_reserved_connections remains as a final reserve in case reserved_connections has been exhausted. Patch by Nathan Bossart. Reviewed by Tushar Ahuja and by me. Discussion: http://postgr.es/m/20230119194601.GA4105788@nathanxps13
1 parent fe00fec commit 6e2775e

File tree

10 files changed

+115
-25
lines changed

10 files changed

+115
-25
lines changed

doc/src/sgml/config.sgml

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,37 @@ include_dir 'conf.d'
708708
</listitem>
709709
</varlistentry>
710710

711+
<varlistentry id="guc-reserved-connections" xreflabel="reserved_connections">
712+
<term><varname>reserved_connections</varname> (<type>integer</type>)
713+
<indexterm>
714+
<primary><varname>reserved_connections</varname> configuration parameter</primary>
715+
</indexterm>
716+
</term>
717+
<listitem>
718+
<para>
719+
Determines the number of connection <quote>slots</quote> that are
720+
reserved for connections by roles with privileges of the
721+
<link linkend="predefined-roles-table"><literal>pg_used_reserved_connections</literal></link>
722+
role. Whenever the number of free connection slots is greater than
723+
<xref linkend="guc-superuser-reserved-connections"/> but less than or
724+
equal to the sum of <varname>superuser_reserved_connections</varname>
725+
and <varname>reserved_connections</varname>, new connections will be
726+
accepted only for superusers and roles with privileges of
727+
<literal>pg_use_reserved_connections</literal>. If
728+
<varname>superuser_reserved_connections</varname> or fewer connection
729+
slots are available, new connections will be accepted only for
730+
superusers.
731+
</para>
732+
733+
<para>
734+
The default value is zero connections. The value must be less than
735+
<varname>max_connections</varname> minus
736+
<varname>superuser_reserved_connections</varname>. This parameter can
737+
only be set at server start.
738+
</para>
739+
</listitem>
740+
</varlistentry>
741+
711742
<varlistentry id="guc-superuser-reserved-connections"
712743
xreflabel="superuser_reserved_connections">
713744
<term><varname>superuser_reserved_connections</varname>
@@ -725,12 +756,16 @@ include_dir 'conf.d'
725756
number of active concurrent connections is at least
726757
<varname>max_connections</varname> minus
727758
<varname>superuser_reserved_connections</varname>, new
728-
connections will be accepted only for superusers.
759+
connections will be accepted only for superusers. The connection slots
760+
reserved by this parameter are intended as final reserve for emergency
761+
use after the slots reserved by
762+
<xref linkend="guc-reserved-connections"/> have been exhausted.
729763
</para>
730764

731765
<para>
732766
The default value is three connections. The value must be less
733-
than <varname>max_connections</varname>.
767+
than <varname>max_connections</varname> minus
768+
<varname>reserved_connections</varname>.
734769
This parameter can only be set at server start.
735770
</para>
736771
</listitem>

doc/src/sgml/user-manag.sgml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,11 @@ DROP ROLE doomed_role;
689689
and <link linkend="sql-lock"><command>LOCK TABLE</command></link> on all
690690
relations.</entry>
691691
</row>
692+
<row>
693+
<entry>pg_use_reserved_connections</entry>
694+
<entry>Allow use of connection slots reserved via
695+
<xref linkend="guc-reserved-connections"/>.</entry>
696+
</row>
692697
</tbody>
693698
</tgroup>
694699
</table>

src/backend/postmaster/postmaster.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,24 @@ char *ListenAddresses;
205205

206206
/*
207207
* SuperuserReservedConnections is the number of backends reserved for
208-
* superuser use. This number is taken out of the pool size given by
209-
* MaxConnections so number of backend slots available to non-superusers is
210-
* (MaxConnections - SuperuserReservedConnections). Note what this really
211-
* means is "if there are <= SuperuserReservedConnections connections
212-
* available, only superusers can make new connections" --- pre-existing
213-
* superuser connections don't count against the limit.
208+
* superuser use, and ReservedConnections is the number of backends reserved
209+
* for use by roles with privileges of the pg_use_reserved_connections
210+
* predefined role. These are taken out of the pool of MaxConnections backend
211+
* slots, so the number of backend slots available for roles that are neither
212+
* superuser nor have privileges of pg_use_reserved_connections is
213+
* (MaxConnections - SuperuserReservedConnections - ReservedConnections).
214+
*
215+
* If the number of remaining slots is less than or equal to
216+
* SuperuserReservedConnections, only superusers can make new connections. If
217+
* the number of remaining slots is greater than SuperuserReservedConnections
218+
* but less than or equal to
219+
* (SuperuserReservedConnections + ReservedConnections), only superusers and
220+
* roles with privileges of pg_use_reserved_connections can make new
221+
* connections. Note that pre-existing superuser and
222+
* pg_use_reserved_connections connections don't count against the limits.
214223
*/
215224
int SuperuserReservedConnections;
225+
int ReservedConnections;
216226

217227
/* The socket(s) we're listening to. */
218228
#define MAXLISTEN 64
@@ -908,11 +918,12 @@ PostmasterMain(int argc, char *argv[])
908918
/*
909919
* Check for invalid combinations of GUC settings.
910920
*/
911-
if (SuperuserReservedConnections >= MaxConnections)
921+
if (SuperuserReservedConnections + ReservedConnections >= MaxConnections)
912922
{
913-
write_stderr("%s: superuser_reserved_connections (%d) must be less than max_connections (%d)\n",
923+
write_stderr("%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must be less than max_connections (%d)\n",
914924
progname,
915-
SuperuserReservedConnections, MaxConnections);
925+
SuperuserReservedConnections, ReservedConnections,
926+
MaxConnections);
916927
ExitPostmaster(1);
917928
}
918929
if (XLogArchiveMode > ARCHIVE_MODE_OFF && wal_level == WAL_LEVEL_MINIMAL)

src/backend/storage/lmgr/proc.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -645,27 +645,33 @@ GetStartupBufferPinWaitBufId(void)
645645
}
646646

647647
/*
648-
* Check whether there are at least N free PGPROC objects.
648+
* Check whether there are at least N free PGPROC objects. If false is
649+
* returned, *nfree will be set to the number of free PGPROC objects.
650+
* Otherwise, *nfree will be set to n.
649651
*
650652
* Note: this is designed on the assumption that N will generally be small.
651653
*/
652654
bool
653-
HaveNFreeProcs(int n)
655+
HaveNFreeProcs(int n, int *nfree)
654656
{
655657
dlist_iter iter;
656658

659+
Assert(n > 0);
660+
Assert(nfree);
661+
657662
SpinLockAcquire(ProcStructLock);
658663

664+
*nfree = 0;
659665
dlist_foreach(iter, &ProcGlobal->freeProcs)
660666
{
661-
n--;
662-
if (n == 0)
667+
(*nfree)++;
668+
if (*nfree == n)
663669
break;
664670
}
665671

666672
SpinLockRelease(ProcStructLock);
667673

668-
return (n <= 0);
674+
return (*nfree == n);
669675
}
670676

671677
/*

src/backend/utils/init/postinit.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ InitPostgres(const char *in_dbname, Oid dboid,
719719
bool am_superuser;
720720
char *fullpath;
721721
char dbname[NAMEDATALEN];
722+
int nfree = 0;
722723

723724
elog(DEBUG3, "InitPostgres");
724725

@@ -922,16 +923,30 @@ InitPostgres(const char *in_dbname, Oid dboid,
922923
}
923924

924925
/*
925-
* The last few connection slots are reserved for superusers. Replication
926-
* connections are drawn from slots reserved with max_wal_senders and not
927-
* limited by max_connections or superuser_reserved_connections.
926+
* The last few connection slots are reserved for superusers and roles with
927+
* privileges of pg_use_reserved_connections. Replication connections are
928+
* drawn from slots reserved with max_wal_senders and are not limited by
929+
* max_connections, superuser_reserved_connections, or
930+
* reserved_connections.
931+
*
932+
* Note: At this point, the new backend has already claimed a proc struct,
933+
* so we must check whether the number of free slots is strictly less than
934+
* the reserved connection limits.
928935
*/
929936
if (!am_superuser && !am_walsender &&
930-
SuperuserReservedConnections > 0 &&
931-
!HaveNFreeProcs(SuperuserReservedConnections))
932-
ereport(FATAL,
933-
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
934-
errmsg("remaining connection slots are reserved for superusers")));
937+
(SuperuserReservedConnections + ReservedConnections) > 0 &&
938+
!HaveNFreeProcs(SuperuserReservedConnections + ReservedConnections, &nfree))
939+
{
940+
if (nfree < SuperuserReservedConnections)
941+
ereport(FATAL,
942+
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
943+
errmsg("remaining connection slots are reserved for superusers")));
944+
945+
if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
946+
ereport(FATAL,
947+
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
948+
errmsg("remaining connection slots are reserved for roles with privileges of pg_use_reserved_connections")));
949+
}
935950

936951
/* Check replication permissions needed for walsender processes. */
937952
if (am_walsender)

src/backend/utils/misc/guc_tables.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,6 +2168,17 @@ struct config_int ConfigureNamesInt[] =
21682168
NULL, NULL, NULL
21692169
},
21702170

2171+
{
2172+
{"reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
2173+
gettext_noop("Sets the number of connection slots reserved for roles "
2174+
"with privileges of pg_use_reserved_connections."),
2175+
NULL
2176+
},
2177+
&ReservedConnections,
2178+
0, 0, MAX_BACKENDS,
2179+
NULL, NULL, NULL
2180+
},
2181+
21712182
{
21722183
{"min_dynamic_shared_memory", PGC_POSTMASTER, RESOURCES_MEM,
21732184
gettext_noop("Amount of dynamic shared memory reserved at startup."),

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
# (change requires restart)
6464
#port = 5432 # (change requires restart)
6565
#max_connections = 100 # (change requires restart)
66+
#reserved_connections = 0 # (change requires restart)
6667
#superuser_reserved_connections = 3 # (change requires restart)
6768
#unix_socket_directories = '/tmp' # comma-separated list of directories
6869
# (change requires restart)

src/include/catalog/pg_authid.dat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,10 @@
8989
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
9090
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
9191
rolpassword => '_null_', rolvaliduntil => '_null_' },
92+
{ oid => '4550', oid_symbol => 'ROLE_PG_USE_RESERVED_CONNECTIONS',
93+
rolname => 'pg_use_reserved_connections', rolsuper => 'f', rolinherit => 't',
94+
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
95+
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
96+
rolpassword => '_null_', rolvaliduntil => '_null_' },
9297

9398
]

src/include/postmaster/postmaster.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
/* GUC options */
1717
extern PGDLLIMPORT bool EnableSSL;
1818
extern PGDLLIMPORT int SuperuserReservedConnections;
19+
extern PGDLLIMPORT int ReservedConnections;
1920
extern PGDLLIMPORT int PostPortNumber;
2021
extern PGDLLIMPORT int Unix_socket_permissions;
2122
extern PGDLLIMPORT char *Unix_socket_group;

src/include/storage/proc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ extern void InitAuxiliaryProcess(void);
445445
extern void SetStartupBufferPinWaitBufId(int bufid);
446446
extern int GetStartupBufferPinWaitBufId(void);
447447

448-
extern bool HaveNFreeProcs(int n);
448+
extern bool HaveNFreeProcs(int n, int *nfree);
449449
extern void ProcReleaseLocks(bool isCommit);
450450

451451
extern ProcWaitStatus ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy