diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/postmaster/postmaster.c | 29 | ||||
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 16 | ||||
-rw-r--r-- | src/backend/utils/init/postinit.c | 31 | ||||
-rw-r--r-- | src/backend/utils/misc/guc_tables.c | 11 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 1 | ||||
-rw-r--r-- | src/include/catalog/pg_authid.dat | 5 | ||||
-rw-r--r-- | src/include/postmaster/postmaster.h | 1 | ||||
-rw-r--r-- | src/include/storage/proc.h | 2 |
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); |