diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index bc8b859f30..bbec926434 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.285 2002/08/18 03:03:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.286 2002/08/29 21:02:12 momjian Exp $ * * NOTES * @@ -151,6 +151,18 @@ char *VirtualHost; */ int MaxBackends = DEF_MAXBACKENDS; +/* + * ReservedBackends is the number of backends reserved for superuser use. + * This number is taken out of the pool size given by MaxBackends so + * number of backend slots available to none super users is + * (MaxBackends - ReservedBackends). Note, existing super user + * connections are not taken into account once this lower limit has + * been reached, i.e. superuser connections made before the lower limit + * is reached always count towards that limit and are not taken from + * ReservedBackends. + */ +int ReservedBackends = 2; + static char *progname = (char *) NULL; @@ -567,6 +579,12 @@ PostmasterMain(int argc, char *argv[]) ProcessConfigFile(PGC_POSTMASTER); + /* + * Force an exit if ReservedBackends is not less than MaxBackends. + */ + if (ReservedBackends >= MaxBackends) + elog(FATAL,"superuser_reserved_connections must be less than max_connections."); + /* * Now that we are done processing the postmaster arguments, reset * getopt(3) library so that it will work correctly in subprocesses. diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index 940ab32b33..745a9c068d 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.49 2002/06/20 20:29:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.50 2002/08/29 21:02:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -538,3 +538,27 @@ BackendIdGetProc(BackendId procId) return NULL; } + +/* + * CountEmptyBackendSlots - count empty slots in backend process table + * + * Doesn't count since the procState array could be large and we've already + * allowed for that by running a freeBackends counter in the SI segment. + * Unlike CountActiveBackends() we do not need to interrogate the + * backends to determine the free slot count. + * Goes for a lock despite being a trival look up in case other backends + * are busy starting or exiting since there is scope for confusion. + */ +int +CountEmptyBackendSlots(void) +{ + int count; + + LWLockAcquire(SInvalLock, LW_SHARED); + + count = shmInvalBuffer->freeBackends; + + LWLockRelease(SInvalLock); + + return count; +} diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index c88055c07b..b4ab1689f9 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.47 2002/06/20 20:29:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.48 2002/08/29 21:02:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -60,6 +60,7 @@ SIBufferInit(int maxBackends) segP->maxMsgNum = 0; segP->lastBackend = 0; segP->maxBackends = maxBackends; + segP->freeBackends = maxBackends; /* The buffer[] array is initially all unused, so we need not fill it */ @@ -91,6 +92,13 @@ SIBackendInit(SISeg *segP) int index; ProcState *stateP = NULL; + if (segP->freeBackends == 0) + { + /* out of procState slots */ + MyBackendId = InvalidBackendId; + return 0; + } + /* Look for a free entry in the procState array */ for (index = 0; index < segP->lastBackend; index++) { @@ -103,18 +111,9 @@ SIBackendInit(SISeg *segP) if (stateP == NULL) { - if (segP->lastBackend < segP->maxBackends) - { - stateP = &segP->procState[segP->lastBackend]; - Assert(stateP->nextMsgNum < 0); - segP->lastBackend++; - } - else - { - /* out of procState slots */ - MyBackendId = InvalidBackendId; - return 0; - } + stateP = &segP->procState[segP->lastBackend]; + Assert(stateP->nextMsgNum < 0); + segP->lastBackend++; } MyBackendId = (stateP - &segP->procState[0]) + 1; @@ -123,6 +122,9 @@ SIBackendInit(SISeg *segP) elog(DEBUG1, "SIBackendInit: backend id %d", MyBackendId); #endif /* INVALIDDEBUG */ + /* Reduce free slot count */ + segP->freeBackends--; + /* mark myself active, with all extant messages already read */ stateP->nextMsgNum = segP->maxMsgNum; stateP->resetState = false; @@ -166,6 +168,9 @@ CleanupInvalidationState(int status, Datum arg) } segP->lastBackend = i; + /* Adjust free slot count */ + segP->freeBackends++; + LWLockRelease(SInvalLock); } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index f36c1d981f..b02e371a81 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.110 2002/08/29 07:22:28 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.111 2002/08/29 21:02:12 momjian Exp $ * * *------------------------------------------------------------------------- @@ -395,6 +395,16 @@ InitPostgres(const char *dbname, const char *username) /* close the transaction we started above */ if (!bootstrap) CommitTransactionCommand(); + + /* + * Check a normal user hasn't connected to a superuser reserved slot. + * Do this here since we need the user information and that only happens + * after we've started bringing the shared memory online. So we wait + * until we've registered exit handlers and potentially shut an open + * transaction down for an as safety conscious rejection as possible. + */ + if (CountEmptyBackendSlots() < ReservedBackends && !superuser()) + elog(ERROR, "Non-superuser connection limit exceeded"); } /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5114fcc38f..e88882def4 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.86 2002/08/29 17:14:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.87 2002/08/29 21:02:12 momjian Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -537,13 +537,20 @@ static struct config_int /* * Note: There is some postprocessing done in PostmasterMain() to make * sure the buffers are at least twice the number of backends, so the - * constraints here are partially unused. + * constraints here are partially unused. Similarly, the superuser + * reserved number is checked to ensure it is less than the max + * backends number. */ { { "max_connections", PGC_POSTMASTER }, &MaxBackends, DEF_MAXBACKENDS, 1, INT_MAX, NULL, NULL }, + { + { "superuser_reserved_connections", PGC_POSTMASTER }, &ReservedBackends, + 2, 0, INT_MAX, NULL, NULL + }, + { { "shared_buffers", PGC_POSTMASTER }, &NBuffers, DEF_NBUFFERS, 16, INT_MAX, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c3e065ecdb..11e9caaabc 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -31,6 +31,7 @@ #ssl = false #max_connections = 32 +#superuser_reserved_connections = 2 #port = 5432 #hostname_lookup = false diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index f2f6f5c676..fce4fea4b4 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: miscadmin.h,v 1.106 2002/06/20 20:29:42 momjian Exp $ + * $Id: miscadmin.h,v 1.107 2002/08/29 21:02:12 momjian Exp $ * * NOTES * some of the information in this file should be moved to @@ -179,6 +179,7 @@ extern bool NetServer; extern bool EnableSSL; extern bool SilentMode; extern int MaxBackends; +extern int ReservedBackends; extern int NBuffers; extern int PostPortNumber; extern int Unix_socket_permissions; diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h index 7af8f44447..1188c68c95 100644 --- a/src/include/storage/sinval.h +++ b/src/include/storage/sinval.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: sinval.h,v 1.28 2002/06/20 20:29:52 momjian Exp $ + * $Id: sinval.h,v 1.29 2002/08/29 21:02:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -89,4 +89,6 @@ extern int CountActiveBackends(void); /* Use "struct PGPROC", not PGPROC, to avoid including proc.h here */ extern struct PGPROC *BackendIdGetProc(BackendId procId); +extern int CountEmptyBackendSlots(void); + #endif /* SINVAL_H */ diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h index 3e95342c9f..39c895026b 100644 --- a/src/include/storage/sinvaladt.h +++ b/src/include/storage/sinvaladt.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: sinvaladt.h,v 1.32 2002/06/20 20:29:52 momjian Exp $ + * $Id: sinvaladt.h,v 1.33 2002/08/29 21:02:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -85,6 +85,7 @@ typedef struct SISeg int lastBackend; /* index of last active procState entry, * +1 */ int maxBackends; /* size of procState array */ + int freeBackends; /* number of empty procState slots */ /* * Circular buffer holding shared-inval messages