aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/postmaster/postmaster.c29
-rw-r--r--src/backend/storage/lmgr/proc.c16
-rw-r--r--src/backend/utils/init/postinit.c31
-rw-r--r--src/backend/utils/misc/guc_tables.c11
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample1
-rw-r--r--src/include/catalog/pg_authid.dat5
-rw-r--r--src/include/postmaster/postmaster.h1
-rw-r--r--src/include/storage/proc.h2
8 files changed, 73 insertions, 23 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3f799c4ac82..aca1ef91b57 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -205,14 +205,24 @@ char *ListenAddresses;
/*
* SuperuserReservedConnections is the number of backends reserved for
- * superuser use. This number is taken out of the pool size given by
- * MaxConnections so number of backend slots available to non-superusers is
- * (MaxConnections - SuperuserReservedConnections). Note what this really
- * means is "if there are <= SuperuserReservedConnections connections
- * available, only superusers can make new connections" --- pre-existing
- * superuser connections don't count against the limit.
+ * superuser use, and ReservedConnections is the number of backends reserved
+ * for use by roles with privileges of the pg_use_reserved_connections
+ * predefined role. These are taken out of the pool of MaxConnections backend
+ * slots, so the number of backend slots available for roles that are neither
+ * superuser nor have privileges of pg_use_reserved_connections is
+ * (MaxConnections - SuperuserReservedConnections - ReservedConnections).
+ *
+ * If the number of remaining slots is less than or equal to
+ * SuperuserReservedConnections, only superusers can make new connections. If
+ * the number of remaining slots is greater than SuperuserReservedConnections
+ * but less than or equal to
+ * (SuperuserReservedConnections + ReservedConnections), only superusers and
+ * roles with privileges of pg_use_reserved_connections can make new
+ * connections. Note that pre-existing superuser and
+ * pg_use_reserved_connections connections don't count against the limits.
*/
int SuperuserReservedConnections;
+int ReservedConnections;
/* The socket(s) we're listening to. */
#define MAXLISTEN 64
@@ -908,11 +918,12 @@ PostmasterMain(int argc, char *argv[])
/*
* Check for invalid combinations of GUC settings.
*/
- if (SuperuserReservedConnections >= MaxConnections)
+ if (SuperuserReservedConnections + ReservedConnections >= MaxConnections)
{
- write_stderr("%s: superuser_reserved_connections (%d) must be less than max_connections (%d)\n",
+ write_stderr("%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must be less than max_connections (%d)\n",
progname,
- SuperuserReservedConnections, MaxConnections);
+ SuperuserReservedConnections, ReservedConnections,
+ MaxConnections);
ExitPostmaster(1);
}
if (XLogArchiveMode > ARCHIVE_MODE_OFF && wal_level == WAL_LEVEL_MINIMAL)
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index f8ac4edd6ff..22b4278610c 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -645,27 +645,33 @@ GetStartupBufferPinWaitBufId(void)
}
/*
- * Check whether there are at least N free PGPROC objects.
+ * Check whether there are at least N free PGPROC objects. If false is
+ * returned, *nfree will be set to the number of free PGPROC objects.
+ * Otherwise, *nfree will be set to n.
*
* Note: this is designed on the assumption that N will generally be small.
*/
bool
-HaveNFreeProcs(int n)
+HaveNFreeProcs(int n, int *nfree)
{
dlist_iter iter;
+ Assert(n > 0);
+ Assert(nfree);
+
SpinLockAcquire(ProcStructLock);
+ *nfree = 0;
dlist_foreach(iter, &ProcGlobal->freeProcs)
{
- n--;
- if (n == 0)
+ (*nfree)++;
+ if (*nfree == n)
break;
}
SpinLockRelease(ProcStructLock);
- return (n <= 0);
+ return (*nfree == n);
}
/*
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 40f145e0ab1..2f07ca7a0e1 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -719,6 +719,7 @@ InitPostgres(const char *in_dbname, Oid dboid,
bool am_superuser;
char *fullpath;
char dbname[NAMEDATALEN];
+ int nfree = 0;
elog(DEBUG3, "InitPostgres");
@@ -922,16 +923,30 @@ InitPostgres(const char *in_dbname, Oid dboid,
}
/*
- * The last few connection slots are reserved for superusers. Replication
- * connections are drawn from slots reserved with max_wal_senders and not
- * limited by max_connections or superuser_reserved_connections.
+ * The last few connection slots are reserved for superusers and roles with
+ * privileges of pg_use_reserved_connections. Replication connections are
+ * drawn from slots reserved with max_wal_senders and are not limited by
+ * max_connections, superuser_reserved_connections, or
+ * reserved_connections.
+ *
+ * Note: At this point, the new backend has already claimed a proc struct,
+ * so we must check whether the number of free slots is strictly less than
+ * the reserved connection limits.
*/
if (!am_superuser && !am_walsender &&
- SuperuserReservedConnections > 0 &&
- !HaveNFreeProcs(SuperuserReservedConnections))
- ereport(FATAL,
- (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
- errmsg("remaining connection slots are reserved for superusers")));
+ (SuperuserReservedConnections + ReservedConnections) > 0 &&
+ !HaveNFreeProcs(SuperuserReservedConnections + ReservedConnections, &nfree))
+ {
+ if (nfree < SuperuserReservedConnections)
+ ereport(FATAL,
+ (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
+ errmsg("remaining connection slots are reserved for superusers")));
+
+ if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
+ ereport(FATAL,
+ (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
+ errmsg("remaining connection slots are reserved for roles with privileges of pg_use_reserved_connections")));
+ }
/* Check replication permissions needed for walsender processes. */
if (am_walsender)
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 0fa9fdd3c58..e1753a40fa9 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -2169,6 +2169,17 @@ struct config_int ConfigureNamesInt[] =
},
{
+ {"reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
+ gettext_noop("Sets the number of connection slots reserved for roles "
+ "with privileges of pg_use_reserved_connections."),
+ NULL
+ },
+ &ReservedConnections,
+ 0, 0, MAX_BACKENDS,
+ NULL, NULL, NULL
+ },
+
+ {
{"min_dynamic_shared_memory", PGC_POSTMASTER, RESOURCES_MEM,
gettext_noop("Amount of dynamic shared memory reserved at startup."),
NULL,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 4cceda41622..d06074b86f6 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -63,6 +63,7 @@
# (change requires restart)
#port = 5432 # (change requires restart)
#max_connections = 100 # (change requires restart)
+#reserved_connections = 0 # (change requires restart)
#superuser_reserved_connections = 3 # (change requires restart)
#unix_socket_directories = '/tmp' # comma-separated list of directories
# (change requires restart)
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 2a2fee7d283..f2e5663c9fe 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -89,5 +89,10 @@
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '4550', oid_symbol => 'ROLE_PG_USE_RESERVED_CONNECTIONS',
+ rolname => 'pg_use_reserved_connections', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
]
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index 0e4b8ded344..3b3889c58c0 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -16,6 +16,7 @@
/* GUC options */
extern PGDLLIMPORT bool EnableSSL;
extern PGDLLIMPORT int SuperuserReservedConnections;
+extern PGDLLIMPORT int ReservedConnections;
extern PGDLLIMPORT int PostPortNumber;
extern PGDLLIMPORT int Unix_socket_permissions;
extern PGDLLIMPORT char *Unix_socket_group;
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index dd45b8ee9b7..4258cd92c9c 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -445,7 +445,7 @@ extern void InitAuxiliaryProcess(void);
extern void SetStartupBufferPinWaitBufId(int bufid);
extern int GetStartupBufferPinWaitBufId(void);
-extern bool HaveNFreeProcs(int n);
+extern bool HaveNFreeProcs(int n, int *nfree);
extern void ProcReleaseLocks(bool isCommit);
extern ProcWaitStatus ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable);