diff options
author | Tom Lane | 2005-08-20 23:26:37 +0000 |
---|---|---|
committer | Tom Lane | 2005-08-20 23:26:37 +0000 |
commit | e54f689c37c48141d6bd942dbdbe6fe5f13bb0b8 (patch) | |
tree | c285a45dd63486cc08abf5608989f054bfcf0831 | |
parent | e7abf58cdb1a15d175532d9623b0a121d495e32a (diff) |
Convert the arithmetic for shared memory size calculation from 'int'
to 'Size' (that is, size_t), and install overflow detection checks in it.
This allows us to remove the former arbitrary restrictions on NBuffers
etc. It won't make any difference in a 32-bit machine, but in a 64-bit
machine you could theoretically have terabytes of shared buffers.
(How efficiently we could manage 'em remains to be seen.) Similarly,
num_temp_buffers, work_mem, and maintenance_work_mem can be set above
2Gb on a 64-bit machine. Original patch from Koichi Suzuki, additional
work by moi.
50 files changed, 726 insertions, 227 deletions
@@ -18063,6 +18063,422 @@ _ACEOF +# And one for the size of size_t (enables tweaks for > 32bit address space) +echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_size_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 + +echo "$as_me:$LINENO: checking size of size_t" >&5 +echo $ECHO_N "checking size of size_t... $ECHO_C" >&6 +if test "${ac_cv_sizeof_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_size_t" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (size_t))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (size_t))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (size_t))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (size_t))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (size_t))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_size_t=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (size_t), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (size_t), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (size_t)); } +unsigned long ulongval () { return (long) (sizeof (size_t)); } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (size_t))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (size_t)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (size_t)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_size_t=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (size_t), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (size_t), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_size_t=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_size_t" >&5 +echo "${ECHO_T}$ac_cv_sizeof_size_t" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t +_ACEOF + + + # Determine memory alignment requirements for the basic C data types. echo "$as_me:$LINENO: checking for short" >&5 diff --git a/configure.in b/configure.in index 4b824cbe80..6b4c05a665 100644 --- a/configure.in +++ b/configure.in @@ -1132,6 +1132,9 @@ fi # Need a #define for the size of Datum (unsigned long) AC_CHECK_SIZEOF([unsigned long]) +# And one for the size of size_t (enables tweaks for > 32bit address space) +AC_CHECK_SIZEOF([size_t]) + # Determine memory alignment requirements for the basic C data types. PGAC_CHECK_ALIGNOF(short) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 78d6cd2cd1..9dffed89ae 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -144,8 +144,7 @@ TransactionIdGetStatus(TransactionId xid) /* * Initialization of shared memory for CLOG */ - -int +Size CLOGShmemSize(void) { return SimpleLruShmemSize(); diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index f0b625d35d..3fd53a4eec 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1159,13 +1159,20 @@ AtEOXact_MultiXact(void) * thus double memory. Also, reserve space for the shared MultiXactState * struct and the per-backend MultiXactId arrays (two of those, too). */ -int +Size MultiXactShmemSize(void) { + Size size; + #define SHARED_MULTIXACT_STATE_SIZE \ - (sizeof(MultiXactStateData) + sizeof(MultiXactId) * 2 * MaxBackends) + add_size(sizeof(MultiXactStateData), \ + mul_size(sizeof(MultiXactId) * 2, MaxBackends)) + + size = SHARED_MULTIXACT_STATE_SIZE; + size = add_size(size, SimpleLruShmemSize()); + size = add_size(size, SimpleLruShmemSize()); - return (SimpleLruShmemSize() * 2 + SHARED_MULTIXACT_STATE_SIZE); + return size; } void diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index b371548867..54d1badfd9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -141,9 +141,10 @@ static int SlruSelectLRUPage(SlruCtl ctl, int pageno); * Initialization of shared memory */ -int +Size SimpleLruShmemSize(void) { + /* we assume NUM_SLRU_BUFFERS isn't so large as to risk overflow */ return BUFFERALIGN(sizeof(SlruSharedData)) + BLCKSZ * NUM_SLRU_BUFFERS; } diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c index bd6f5598ee..ab40011e29 100644 --- a/src/backend/access/transam/subtrans.c +++ b/src/backend/access/transam/subtrans.c @@ -161,8 +161,7 @@ SubTransGetTopmostTransaction(TransactionId xid) /* * Initialization of shared memory for SUBTRANS */ - -int +Size SUBTRANSShmemSize(void) { return SimpleLruShmemSize(); diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 1b19bd6a96..d4fe92e4eb 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -152,13 +152,20 @@ static void ProcessRecords(char *bufptr, TransactionId xid, /* * Initialization of shared memory */ -int +Size TwoPhaseShmemSize(void) { + Size size; + /* Need the fixed struct, the array of pointers, and the GTD structs */ - return MAXALIGN(offsetof(TwoPhaseStateData, prepXacts) + - sizeof(GlobalTransaction) * max_prepared_xacts) + - sizeof(GlobalTransactionData) * max_prepared_xacts; + size = offsetof(TwoPhaseStateData, prepXacts); + size = add_size(size, mul_size(max_prepared_xacts, + sizeof(GlobalTransaction))); + size = MAXALIGN(size); + size = add_size(size, mul_size(max_prepared_xacts, + sizeof(GlobalTransactionData))); + + return size; } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index d272924d26..9c60cf6719 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -91,31 +91,6 @@ #endif #endif -/* - * Limitation of buffer-alignment for direct io depend on OS and filesystem, - * but BLCKSZ is assumed to be enough for it. - */ -#ifdef O_DIRECT -#define ALIGNOF_XLOG_BUFFER BLCKSZ -#else -#define ALIGNOF_XLOG_BUFFER MAXIMUM_ALIGNOF -#endif - -/* - * Switch the alignment routine because ShmemAlloc() returns a max-aligned - * buffer and ALIGNOF_XLOG_BUFFER may be greater than MAXIMUM_ALIGNOF. - */ -#if ALIGNOF_XLOG_BUFFER <= MAXIMUM_ALIGNOF -#define XLOG_BUFFER_ALIGN(LEN) MAXALIGN((LEN)) -#else -#define XLOG_BUFFER_ALIGN(LEN) ((LEN) + (ALIGNOF_XLOG_BUFFER)) -#endif -/* assume sizeof(ptrdiff_t) == sizeof(void*) */ -#define POINTERALIGN(ALIGNVAL,PTR) \ - ((char *)(((ptrdiff_t) (PTR) + (ALIGNVAL-1)) & ~((ptrdiff_t) (ALIGNVAL-1)))) -#define XLOG_BUFFER_POINTERALIGN(PTR) \ - POINTERALIGN((ALIGNOF_XLOG_BUFFER), (PTR)) - #ifdef OPEN_DATASYNC_FLAG #define DEFAULT_SYNC_METHOD_STR "open_datasync" #define DEFAULT_SYNC_METHOD SYNC_METHOD_OPEN @@ -135,6 +110,17 @@ #endif +/* + * Limitation of buffer-alignment for direct IO depends on OS and filesystem, + * but BLCKSZ is assumed to be enough for it. + */ +#ifdef O_DIRECT +#define ALIGNOF_XLOG_BUFFER BLCKSZ +#else +#define ALIGNOF_XLOG_BUFFER ALIGNOF_BUFFER +#endif + + /* File path names (all relative to $PGDATA) */ #define BACKUP_LABEL_FILE "backup_label" #define RECOVERY_COMMAND_FILE "recovery.conf" @@ -173,8 +159,6 @@ static int open_sync_bit = DEFAULT_SYNC_FLAGBIT; #define XLOG_SYNC_BIT (enableFsync ? open_sync_bit : 0) -#define MinXLOGbuffers 4 - /* * ThisTimeLineID will be same in all backends --- it identifies current @@ -3615,16 +3599,27 @@ UpdateControlFile(void) /* * Initialization of shared memory for XLOG */ - -int +Size XLOGShmemSize(void) { - if (XLOGbuffers < MinXLOGbuffers) - XLOGbuffers = MinXLOGbuffers; + Size size; - return XLOG_BUFFER_ALIGN(sizeof(XLogCtlData) + sizeof(XLogRecPtr) * XLOGbuffers) - + BLCKSZ * XLOGbuffers + - MAXALIGN(sizeof(ControlFileData)); + /* XLogCtl */ + size = sizeof(XLogCtlData); + /* xlblocks array */ + size = add_size(size, mul_size(sizeof(XLogRecPtr), XLOGbuffers)); + /* extra alignment padding for XLOG I/O buffers */ + size = add_size(size, ALIGNOF_XLOG_BUFFER); + /* and the buffers themselves */ + size = add_size(size, mul_size(BLCKSZ, XLOGbuffers)); + + /* + * Note: we don't count ControlFileData, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us + * use this routine again below to compute the actual allocation size. + */ + + return size; } void @@ -3632,17 +3627,10 @@ XLOGShmemInit(void) { bool foundXLog, foundCFile; - - /* this must agree with space requested by XLOGShmemSize() */ - if (XLOGbuffers < MinXLOGbuffers) - XLOGbuffers = MinXLOGbuffers; + char *allocptr; XLogCtl = (XLogCtlData *) - ShmemInitStruct("XLOG Ctl", - XLOG_BUFFER_ALIGN(sizeof(XLogCtlData) + - sizeof(XLogRecPtr) * XLOGbuffers) - + BLCKSZ * XLOGbuffers, - &foundXLog); + ShmemInitStruct("XLOG Ctl", XLOGShmemSize(), &foundXLog); ControlFile = (ControlFileData *) ShmemInitStruct("Control File", sizeof(ControlFileData), &foundCFile); @@ -3660,17 +3648,16 @@ XLOGShmemInit(void) * a multiple of the alignment for same, so no extra alignment padding * is needed here. */ - XLogCtl->xlblocks = (XLogRecPtr *) - (((char *) XLogCtl) + sizeof(XLogCtlData)); + allocptr = ((char *) XLogCtl) + sizeof(XLogCtlData); + XLogCtl->xlblocks = (XLogRecPtr *) allocptr; memset(XLogCtl->xlblocks, 0, sizeof(XLogRecPtr) * XLOGbuffers); + allocptr += sizeof(XLogRecPtr) * XLOGbuffers; /* - * Here, on the other hand, we must MAXALIGN to ensure the page - * buffers have worst-case alignment. + * Align the start of the page buffers to an ALIGNOF_XLOG_BUFFER boundary. */ - XLogCtl->pages = XLOG_BUFFER_POINTERALIGN( - ((char *) XLogCtl) - + sizeof(XLogCtlData) + sizeof(XLogRecPtr) * XLOGbuffers); + allocptr = (char *) TYPEALIGN(ALIGNOF_XLOG_BUFFER, allocptr); + XLogCtl->pages = allocptr; memset(XLogCtl->pages, 0, BLCKSZ * XLOGbuffers); /* @@ -3728,8 +3715,9 @@ BootStrapXLOG(void) /* First timeline ID is always 1 */ ThisTimeLineID = 1; - buffer = (char *) malloc(BLCKSZ + ALIGNOF_XLOG_BUFFER); - page = (XLogPageHeader) XLOG_BUFFER_POINTERALIGN(buffer); + /* page buffer must be aligned suitably for O_DIRECT */ + buffer = (char *) palloc(BLCKSZ + ALIGNOF_XLOG_BUFFER); + page = (XLogPageHeader) TYPEALIGN(ALIGNOF_XLOG_BUFFER, buffer); memset(page, 0, BLCKSZ); /* Set up information for the initial checkpoint record */ @@ -3824,7 +3812,7 @@ BootStrapXLOG(void) BootStrapSUBTRANS(); BootStrapMultiXact(); - free(buffer); + pfree(buffer); } static char * diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index a10a73eeaf..c2d5f83e06 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -954,16 +954,16 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats) static void lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks) { - int maxtuples; + long maxtuples; int maxpages; - maxtuples = (int) ((maintenance_work_mem * 1024L) / sizeof(ItemPointerData)); + maxtuples = (maintenance_work_mem * 1024L) / sizeof(ItemPointerData); + maxtuples = Min(maxtuples, INT_MAX); /* stay sane if small maintenance_work_mem */ - if (maxtuples < MAX_TUPLES_PER_PAGE) - maxtuples = MAX_TUPLES_PER_PAGE; + maxtuples = Max(maxtuples, MAX_TUPLES_PER_PAGE); vacrelstats->num_dead_tuples = 0; - vacrelstats->max_dead_tuples = maxtuples; + vacrelstats->max_dead_tuples = (int) maxtuples; vacrelstats->dead_tuples = (ItemPointer) palloc(maxtuples * sizeof(ItemPointerData)); diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index a1fe5e95b9..a10ff2b1f1 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -51,7 +51,7 @@ typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */ unsigned long UsedShmemSegID = 0; void *UsedShmemSegAddr = NULL; -static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size); +static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size); static void IpcMemoryDetach(int status, Datum shmaddr); static void IpcMemoryDelete(int status, Datum shmId); static PGShmemHeader *PGSharedMemoryAttach(IpcMemoryKey key, @@ -71,7 +71,7 @@ static PGShmemHeader *PGSharedMemoryAttach(IpcMemoryKey key, * print out an error and abort. Other types of errors are not recoverable. */ static void * -InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size) +InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size) { IpcMemoryId shmid; void *memAddress; @@ -99,14 +99,14 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size) */ ereport(FATAL, (errmsg("could not create shared memory segment: %m"), - errdetail("Failed system call was shmget(key=%lu, size=%u, 0%o).", - (unsigned long) memKey, size, + errdetail("Failed system call was shmget(key=%lu, size=%lu, 0%o).", + (unsigned long) memKey, (unsigned long) size, IPC_CREAT | IPC_EXCL | IPCProtection), (errno == EINVAL) ? errhint("This error usually means that PostgreSQL's request for a shared memory " "segment exceeded your kernel's SHMMAX parameter. You can either " "reduce the request size or reconfigure the kernel with larger SHMMAX. " - "To reduce the request size (currently %u bytes), reduce " + "To reduce the request size (currently %lu bytes), reduce " "PostgreSQL's shared_buffers parameter (currently %d) and/or " "its max_connections parameter (currently %d).\n" "If the request size is already small, it's possible that it is less than " @@ -114,28 +114,28 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size) "reconfiguring SHMMIN is called for.\n" "The PostgreSQL documentation contains more information about shared " "memory configuration.", - size, NBuffers, MaxBackends) : 0, + (unsigned long) size, NBuffers, MaxBackends) : 0, (errno == ENOMEM) ? errhint("This error usually means that PostgreSQL's request for a shared " "memory segment exceeded available memory or swap space. " - "To reduce the request size (currently %u bytes), reduce " + "To reduce the request size (currently %lu bytes), reduce " "PostgreSQL's shared_buffers parameter (currently %d) and/or " "its max_connections parameter (currently %d).\n" "The PostgreSQL documentation contains more information about shared " "memory configuration.", - size, NBuffers, MaxBackends) : 0, + (unsigned long) size, NBuffers, MaxBackends) : 0, (errno == ENOSPC) ? errhint("This error does *not* mean that you have run out of disk space. " "It occurs either if all available shared memory IDs have been taken, " "in which case you need to raise the SHMMNI parameter in your kernel, " "or because the system's overall limit for shared memory has been " "reached. If you cannot increase the shared memory limit, " - "reduce PostgreSQL's shared memory request (currently %u bytes), " + "reduce PostgreSQL's shared memory request (currently %lu bytes), " "by reducing its shared_buffers parameter (currently %d) and/or " "its max_connections parameter (currently %d).\n" "The PostgreSQL documentation contains more information about shared " "memory configuration.", - size, NBuffers, MaxBackends) : 0)); + (unsigned long) size, NBuffers, MaxBackends) : 0)); } /* Register on-exit routine to delete the new segment */ @@ -289,7 +289,7 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2) * zero will be passed. */ PGShmemHeader * -PGSharedMemoryCreate(uint32 size, bool makePrivate, int port) +PGSharedMemoryCreate(Size size, bool makePrivate, int port) { IpcMemoryKey NextShmemSegID; void *memAddress; diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index 02dd1ab566..e2c3f39537 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -462,15 +462,19 @@ ReqShutdownHandler(SIGNAL_ARGS) * BgWriterShmemSize * Compute space needed for bgwriter-related shared memory */ -int +Size BgWriterShmemSize(void) { + Size size; + /* * Currently, the size of the requests[] array is arbitrarily set * equal to NBuffers. This may prove too large or small ... */ - return MAXALIGN(sizeof(BgWriterShmemStruct) + - (NBuffers - 1) *sizeof(BgWriterRequest)); + size = offsetof(BgWriterShmemStruct, requests); + size = add_size(size, mul_size(NBuffers, sizeof(BgWriterRequest))); + + return size; } /* diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 6ebd63a098..4f30a04503 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -816,9 +816,9 @@ PostmasterMain(int argc, char *argv[]) * Initialize the child pid/HANDLE arrays for signal handling. */ win32_childPIDArray = (pid_t *) - malloc(NUM_BACKENDARRAY_ELEMS * sizeof(pid_t)); + malloc(mul_size(NUM_BACKENDARRAY_ELEMS, sizeof(pid_t))); win32_childHNDArray = (HANDLE *) - malloc(NUM_BACKENDARRAY_ELEMS * sizeof(HANDLE)); + malloc(mul_size(NUM_BACKENDARRAY_ELEMS, sizeof(HANDLE))); if (!win32_childPIDArray || !win32_childHNDArray) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), @@ -3920,16 +3920,16 @@ restore_backend_variables(BackendParameters *param, Port *port) } -size_t +Size ShmemBackendArraySize(void) { - return (NUM_BACKENDARRAY_ELEMS * sizeof(Backend)); + return mul_size(NUM_BACKENDARRAY_ELEMS, sizeof(Backend)); } void ShmemBackendArrayAllocation(void) { - size_t size = ShmemBackendArraySize(); + Size size = ShmemBackendArraySize(); ShmemBackendArray = (Backend *) ShmemAlloc(size); /* Mark all slots as empty */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index ed38f8d874..37862a8bf9 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -89,7 +89,7 @@ InitBufferPool(void) BufferBlocks = (char *) ShmemInitStruct("Buffer Blocks", - NBuffers * BLCKSZ, &foundBufs); + NBuffers * (Size) BLCKSZ, &foundBufs); if (foundDescs || foundBufs) { @@ -155,8 +155,11 @@ InitBufferPoolAccess(void) /* * Allocate and zero local arrays of per-buffer info. */ - PrivateRefCount = (int32 *) calloc(NBuffers, - sizeof(*PrivateRefCount)); + PrivateRefCount = (int32 *) calloc(NBuffers, sizeof(int32)); + if (!PrivateRefCount) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); } /* @@ -165,19 +168,19 @@ InitBufferPoolAccess(void) * compute the size of shared memory for the buffer pool including * data pages, buffer descriptors, hash tables, etc. */ -int +Size BufferShmemSize(void) { - int size = 0; + Size size = 0; /* size of buffer descriptors */ - size += MAXALIGN(NBuffers * sizeof(BufferDesc)); + size = add_size(size, mul_size(NBuffers, sizeof(BufferDesc))); /* size of data pages */ - size += NBuffers * MAXALIGN(BLCKSZ); + size = add_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size += StrategyShmemSize(); + size = add_size(size, StrategyShmemSize()); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index 1a0303b567..6b2c926673 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -37,7 +37,7 @@ static HTAB *SharedBufHash; * Estimate space needed for mapping hashtable * size is the desired hash table size (possibly more than NBuffers) */ -int +Size BufTableShmemSize(int size) { return hash_estimate_size(size, sizeof(BufferLookupEnt)); diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 2d1ad5516a..4eac94dfba 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -208,16 +208,16 @@ StrategyHintVacuum(bool vacuum_active) * Note: for somewhat historical reasons, the buffer lookup hashtable size * is also determined here. */ -int +Size StrategyShmemSize(void) { - int size = 0; + Size size = 0; /* size of lookup hash table */ - size += BufTableShmemSize(NBuffers); + size = add_size(size, BufTableShmemSize(NBuffers)); /* size of the shared replacement strategy control block */ - size += MAXALIGN(sizeof(BufferStrategyControl)); + size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); return size; } diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 18d3723c57..1ed553a476 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -255,15 +255,13 @@ InitLocalBuffers(void) int i; /* Allocate and zero buffer headers and auxiliary arrays */ - LocalBufferDescriptors = (BufferDesc *) - MemoryContextAllocZero(TopMemoryContext, - nbufs * sizeof(BufferDesc)); - LocalBufferBlockPointers = (Block *) - MemoryContextAllocZero(TopMemoryContext, - nbufs * sizeof(Block)); - LocalRefCount = (int32 *) - MemoryContextAllocZero(TopMemoryContext, - nbufs * sizeof(int32)); + LocalBufferDescriptors = (BufferDesc *) calloc(nbufs, sizeof(BufferDesc)); + LocalBufferBlockPointers = (Block *) calloc(nbufs, sizeof(Block)); + LocalRefCount = (int32 *) calloc(nbufs, sizeof(int32)); + if (!LocalBufferDescriptors || !LocalBufferBlockPointers || !LocalRefCount) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); nextFreeLocalBuf = 0; diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 3643a9e8f1..0c01299992 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -271,11 +271,13 @@ InitFreeSpaceMap(void) bool found; /* Create table header */ - FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header", sizeof(FSMHeader), &found); + FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header", + sizeof(FSMHeader), + &found); if (FreeSpaceMap == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("insufficient shared memory for free space map"))); + errmsg("insufficient shared memory for free space map"))); if (!found) MemSet(FreeSpaceMap, 0, sizeof(FSMHeader)); @@ -308,7 +310,7 @@ InitFreeSpaceMap(void) errmsg("max_fsm_pages must exceed max_fsm_relations * %d", CHUNKPAGES))); - FreeSpaceMap->arena = (char *) ShmemAlloc(nchunks * CHUNKBYTES); + FreeSpaceMap->arena = (char *) ShmemAlloc((Size) nchunks * CHUNKBYTES); if (FreeSpaceMap->arena == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), @@ -322,27 +324,22 @@ InitFreeSpaceMap(void) /* * Estimate amount of shmem space needed for FSM. */ -int +Size FreeSpaceShmemSize(void) { - int size; + Size size; int nchunks; /* table header */ size = MAXALIGN(sizeof(FSMHeader)); /* hash table, including the FSMRelation objects */ - size += hash_estimate_size(MaxFSMRelations + 1, sizeof(FSMRelation)); + size = add_size(size, hash_estimate_size(MaxFSMRelations + 1, + sizeof(FSMRelation))); /* page-storage arena */ nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1; - - if (nchunks >= (INT_MAX / CHUNKBYTES)) - ereport(FATAL, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("max_fsm_pages is too large"))); - - size += MAXALIGN(nchunks * CHUNKBYTES); + size = add_size(size, mul_size(nchunks, CHUNKBYTES)); return size; } diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 360161c961..9176494051 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -61,36 +61,44 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) if (!IsUnderPostmaster) { - int size; + Size size; int numSemas; /* * Size of the Postgres shared-memory block is estimated via * moderately-accurate estimates for the big hogs, plus 100K for * the stuff that's too small to bother with estimating. + * + * We take some care during this phase to ensure that the total + * size request doesn't overflow size_t. If this gets through, + * we don't need to be so careful during the actual allocation + * phase. */ - size = hash_estimate_size(SHMEM_INDEX_SIZE, sizeof(ShmemIndexEnt)); - size += BufferShmemSize(); - size += LockShmemSize(); - size += ProcGlobalShmemSize(); - size += XLOGShmemSize(); - size += CLOGShmemSize(); - size += SUBTRANSShmemSize(); - size += TwoPhaseShmemSize(); - size += MultiXactShmemSize(); - size += LWLockShmemSize(); - size += ProcArrayShmemSize(); - size += SInvalShmemSize(MaxBackends); - size += FreeSpaceShmemSize(); - size += BgWriterShmemSize(); + size = 100000; + size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE, + sizeof(ShmemIndexEnt))); + size = add_size(size, BufferShmemSize()); + size = add_size(size, LockShmemSize()); + size = add_size(size, ProcGlobalShmemSize()); + size = add_size(size, XLOGShmemSize()); + size = add_size(size, CLOGShmemSize()); + size = add_size(size, SUBTRANSShmemSize()); + size = add_size(size, TwoPhaseShmemSize()); + size = add_size(size, MultiXactShmemSize()); + size = add_size(size, LWLockShmemSize()); + size = add_size(size, ProcArrayShmemSize()); + size = add_size(size, SInvalShmemSize()); + size = add_size(size, FreeSpaceShmemSize()); + size = add_size(size, BgWriterShmemSize()); #ifdef EXEC_BACKEND - size += ShmemBackendArraySize(); + size = add_size(size, ShmemBackendArraySize()); #endif - size += 100000; + /* might as well round it off to a multiple of a typical page size */ - size += 8192 - (size % 8192); + size = add_size(size, 8192 - (size % 8192)); - elog(DEBUG3, "invoking IpcMemoryCreate(size=%d)", size); + elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)", + (unsigned long) size); /* * Create the shmem segment @@ -163,7 +171,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) /* * Set up shared-inval messaging */ - CreateSharedInvalidationState(MaxBackends); + CreateSharedInvalidationState(); /* * Set up free-space map diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index ad2824687d..5f84098490 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -48,7 +48,9 @@ PMSignalInit(void) bool found; PMSignalFlags = (sig_atomic_t *) - ShmemInitStruct("PMSignalFlags", NUM_PMSIGNALS * sizeof(sig_atomic_t), &found); + ShmemInitStruct("PMSignalFlags", + NUM_PMSIGNALS * sizeof(sig_atomic_t), + &found); if (!found) MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t)); diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4b6d6ea6f0..2425f66135 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -81,11 +81,16 @@ static void DisplayXidCache(void); /* * Report shared-memory space needed by CreateSharedProcArray. */ -int +Size ProcArrayShmemSize(void) { - return MAXALIGN(offsetof(ProcArrayStruct, procs) + - (MaxBackends + max_prepared_xacts) * sizeof(PGPROC *)); + Size size; + + size = offsetof(ProcArrayStruct, procs); + size = add_size(size, mul_size(sizeof(PGPROC *), + add_size(MaxBackends, max_prepared_xacts))); + + return size; } /* diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 7c8c954b6e..2c4ead0141 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -141,8 +141,8 @@ InitShmemAllocation(void *seghdr, bool init) void * ShmemAlloc(Size size) { - uint32 newStart; - uint32 newFree; + Size newStart; + Size newFree; void *newSpace; /* use volatile pointer to prevent code rearrangement */ @@ -415,3 +415,40 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) SpinLockRelease(ShmemIndexLock); return structPtr; } + + +/* + * Add two Size values, checking for overflow + */ +Size +add_size(Size s1, Size s2) +{ + Size result; + + result = s1 + s2; + /* We are assuming Size is an unsigned type here... */ + if (result < s1 || result < s2) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("requested shared memory size overflows size_t"))); + return result; +} + +/* + * Multiply two Size values, checking for overflow + */ +Size +mul_size(Size s1, Size s2) +{ + Size result; + + if (s1 == 0 || s2 == 0) + return 0; + result = s1 * s2; + /* We are assuming Size is an unsigned type here... */ + if (result / s2 != s1) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("requested shared memory size overflows size_t"))); + return result; +} diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index 66fb23bce1..a2bef9707d 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -55,10 +55,10 @@ static void ProcessCatchupEvent(void); /* should be called only by the POSTMASTER */ /****************************************************************************/ void -CreateSharedInvalidationState(int maxBackends) +CreateSharedInvalidationState(void) { /* SInvalLock must be initialized already, during LWLock init */ - SIBufferInit(maxBackends); + SIBufferInit(); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 3113f5a222..549767137d 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -32,14 +32,15 @@ static void SISetProcStateInvalid(SISeg *segP); /* * SInvalShmemSize --- return shared-memory space needed */ -int -SInvalShmemSize(int maxBackends) +Size +SInvalShmemSize(void) { - /* - * Figure space needed. Note sizeof(SISeg) includes the first - * ProcState entry. - */ - return sizeof(SISeg) + sizeof(ProcState) * (maxBackends - 1); + Size size; + + size = offsetof(SISeg, procState); + size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); + + return size; } /* @@ -47,16 +48,15 @@ SInvalShmemSize(int maxBackends) * Create and initialize a new SI message buffer */ void -SIBufferInit(int maxBackends) +SIBufferInit(void) { - int segSize; SISeg *segP; int i; bool found; /* Allocate space in shared memory */ - segSize = SInvalShmemSize(maxBackends); - shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer", segSize, &found); + shmInvalBuffer = segP = (SISeg *) + ShmemInitStruct("shmInvalBuffer", SInvalShmemSize(), &found); if (found) return; @@ -64,13 +64,13 @@ SIBufferInit(int maxBackends) segP->minMsgNum = 0; segP->maxMsgNum = 0; segP->lastBackend = 0; - segP->maxBackends = maxBackends; - segP->freeBackends = maxBackends; + segP->maxBackends = MaxBackends; + segP->freeBackends = MaxBackends; /* The buffer[] array is initially all unused, so we need not fill it */ /* Mark all backends inactive */ - for (i = 0; i < maxBackends; i++) + for (i = 0; i < segP->maxBackends; i++) { segP->procState[i].nextMsgNum = -1; /* inactive */ segP->procState[i].resetState = false; diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 74c5ba720d..87888b9527 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -46,7 +46,8 @@ /* This configuration variable is used to set the lock table size */ int max_locks_per_xact; /* set by guc.c */ -#define NLOCKENTS() (max_locks_per_xact * (MaxBackends + max_prepared_xacts)) +#define NLOCKENTS() \ + mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* Record that's written to 2PC state file when a lock is persisted */ @@ -1864,20 +1865,20 @@ next_item: /* * Estimate shared-memory space used for lock tables */ -int +Size LockShmemSize(void) { - int size = 0; + Size size; long max_table_size = NLOCKENTS(); /* lock method headers */ - size += MAX_LOCK_METHODS * MAXALIGN(sizeof(LockMethodData)); + size = MAX_LOCK_METHODS * MAXALIGN(sizeof(LockMethodData)); /* lockHash table */ - size += hash_estimate_size(max_table_size, sizeof(LOCK)); + size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); /* proclockHash table */ - size += hash_estimate_size(max_table_size, sizeof(PROCLOCK)); + size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); /* * Note we count only one pair of hash tables, since the userlocks @@ -1886,7 +1887,7 @@ LockShmemSize(void) * Since the lockHash entry count above is only an estimate, add 10% * safety margin. */ - size += size / 10; + size = add_size(size, size / 10); return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 232c7c3b61..3fca81a317 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -129,17 +129,18 @@ NumLWLocks(void) /* * Compute shmem space needed for LWLocks. */ -int +Size LWLockShmemSize(void) { + Size size; int numLocks = NumLWLocks(); - uint32 spaceLocks; /* Allocate the LWLocks plus space for shared allocation counter. */ - spaceLocks = numLocks * sizeof(LWLock) + 2 * sizeof(int); - spaceLocks = MAXALIGN(spaceLocks); + size = mul_size(numLocks, sizeof(LWLock)); + + size = add_size(size, 2 * sizeof(int)); - return (int) spaceLocks; + return size; } @@ -150,7 +151,7 @@ void CreateLWLocks(void) { int numLocks = NumLWLocks(); - uint32 spaceLocks = LWLockShmemSize(); + Size spaceLocks = LWLockShmemSize(); LWLock *lock; int id; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index a765218838..0b28b93015 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -91,15 +91,19 @@ static bool CheckStatementTimeout(void); /* * Report shared-memory space needed by InitProcGlobal. */ -int +Size ProcGlobalShmemSize(void) { - int size = 0; - - size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ - size += MAXALIGN(NUM_DUMMY_PROCS * sizeof(PGPROC)); /* DummyProcs */ - size += MAXALIGN(MaxBackends * sizeof(PGPROC)); /* MyProcs */ - size += MAXALIGN(sizeof(slock_t)); /* ProcStructLock */ + Size size = 0; + + /* ProcGlobal */ + size = add_size(size, sizeof(PROC_HDR)); + /* DummyProcs */ + size = add_size(size, mul_size(NUM_DUMMY_PROCS, sizeof(PGPROC))); + /* MyProcs */ + size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC))); + /* ProcStructLock */ + size = add_size(size, sizeof(slock_t)); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 5dfd166a84..2cfb9f2834 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -44,6 +44,7 @@ #include "postgres.h" +#include "storage/shmem.h" #include "utils/dynahash.h" #include "utils/hsearch.h" #include "utils/memutils.h" @@ -391,10 +392,10 @@ init_htab(HTAB *hashp, long nelem) * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ -long +Size hash_estimate_size(long num_entries, Size entrysize) { - long size = 0; + Size size; long nBuckets, nSegments, nDirEntries, @@ -412,17 +413,20 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size += MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size += MAXALIGN(nDirEntries * sizeof(HASHSEGMENT)); + size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size += nSegments * MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, + MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); /* elements --- allocated in groups of up to HASHELEMENT_ALLOC_MAX */ elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); elementAllocCnt = Min(num_entries, HASHELEMENT_ALLOC_MAX); elementAllocCnt = Max(elementAllocCnt, 1); nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; - size += nElementAllocs * elementAllocCnt * elementSize; + size = add_size(size, + mul_size(nElementAllocs, + mul_size(elementAllocCnt, elementSize))); return size; } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 7dd80f5115..d6b91eced6 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -78,6 +78,13 @@ #define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new" #endif +/* upper limit for GUC variables measured in kilobytes of memory */ +#if SIZEOF_SIZE_T > 4 +#define MAX_KILOBYTES INT_MAX +#else +#define MAX_KILOBYTES (INT_MAX / 1024) +#endif + /* XXX these should appear in other modules' header files */ extern bool Log_disconnections; extern DLLIMPORT bool check_function_bodies; @@ -1027,6 +1034,10 @@ static struct config_int ConfigureNamesInt[] = * constraints here are partially unused. Similarly, the superuser * reserved number is checked to ensure it is less than the max * backends number. + * + * MaxBackends is limited to INT_MAX/4 because some places compute + * 4*MaxBackends without any overflow check. Likewise we have to + * limit NBuffers to INT_MAX/2. */ { {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS, @@ -1034,7 +1045,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &MaxBackends, - 100, 1, INT_MAX / BLCKSZ, NULL, NULL + 100, 1, INT_MAX / 4, NULL, NULL }, { @@ -1043,7 +1054,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &ReservedBackends, - 2, 0, INT_MAX / BLCKSZ, NULL, NULL + 2, 0, INT_MAX / 4, NULL, NULL }, { @@ -1052,7 +1063,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &NBuffers, - 1000, 16, INT_MAX / BLCKSZ, NULL, NULL + 1000, 16, INT_MAX / 2, NULL, NULL }, { @@ -1061,7 +1072,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &num_temp_buffers, - 1000, 100, INT_MAX / BLCKSZ, NULL, show_num_temp_buffers + 1000, 100, INT_MAX / 2, NULL, show_num_temp_buffers }, { @@ -1094,7 +1105,7 @@ static struct config_int ConfigureNamesInt[] = "temporary disk files.") }, &work_mem, - 1024, 8 * BLCKSZ / 1024, INT_MAX / 1024, NULL, NULL + 1024, 8 * BLCKSZ / 1024, MAX_KILOBYTES, NULL, NULL }, { @@ -1103,7 +1114,7 @@ static struct config_int ConfigureNamesInt[] = gettext_noop("This includes operations such as VACUUM and CREATE INDEX.") }, &maintenance_work_mem, - 16384, 1024, INT_MAX / 1024, NULL, NULL + 16384, 1024, MAX_KILOBYTES, NULL, NULL }, { @@ -1112,7 +1123,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &max_stack_depth, - 2048, 100, INT_MAX / 1024, assign_max_stack_depth, NULL + 2048, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL }, { @@ -1193,7 +1204,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &max_prepared_xacts, - 50, 0, 10000, NULL, NULL + 50, 0, INT_MAX, NULL, NULL }, #ifdef LOCK_DEBUG @@ -1310,7 +1321,7 @@ static struct config_int ConfigureNamesInt[] = NULL }, &XLOGbuffers, - 8, 4, INT_MAX / BLCKSZ, NULL, NULL + 8, 4, INT_MAX, NULL, NULL }, { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index e05ca9fb88..6e08b4cc32 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -88,7 +88,7 @@ #shared_buffers = 1000 # min 16 or max_connections*2, 8KB each #temp_buffers = 1000 # min 100, 8KB each -#max_prepared_transactions = 50 # 0-10000 +#max_prepared_transactions = 50 # can be 0 or more #work_mem = 1024 # min 64, size in KB #maintenance_work_mem = 16384 # min 1024, size in KB #max_stack_depth = 2048 # min 100, size in KB diff --git a/src/include/access/clog.h b/src/include/access/clog.h index b01341057d..f9ea06b4df 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -31,7 +31,7 @@ typedef int XidStatus; extern void TransactionIdSetStatus(TransactionId xid, XidStatus status); extern XidStatus TransactionIdGetStatus(TransactionId xid); -extern int CLOGShmemSize(void); +extern Size CLOGShmemSize(void); extern void CLOGShmemInit(void); extern void BootStrapCLOG(void); extern void StartupCLOG(void); diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index 83e571b031..4a5d47a636 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -48,7 +48,7 @@ extern int GetMultiXactIdMembers(MultiXactId multi, TransactionId **xids); extern void AtEOXact_MultiXact(void); -extern int MultiXactShmemSize(void); +extern Size MultiXactShmemSize(void); extern void MultiXactShmemInit(void); extern void BootStrapMultiXact(void); extern void StartupMultiXact(void); diff --git a/src/include/access/slru.h b/src/include/access/slru.h index db14a9d208..a3baf20a2b 100644 --- a/src/include/access/slru.h +++ b/src/include/access/slru.h @@ -96,7 +96,7 @@ typedef SlruCtlData *SlruCtl; typedef struct SlruFlushData *SlruFlush; -extern int SimpleLruShmemSize(void); +extern Size SimpleLruShmemSize(void); extern void SimpleLruInit(SlruCtl ctl, const char *name, LWLockId ctllock, const char *subdir); extern int SimpleLruZeroPage(SlruCtl ctl, int pageno); diff --git a/src/include/access/subtrans.h b/src/include/access/subtrans.h index 4d6262c745..fe6f1f0568 100644 --- a/src/include/access/subtrans.h +++ b/src/include/access/subtrans.h @@ -15,7 +15,7 @@ extern void SubTransSetParent(TransactionId xid, TransactionId parent); extern TransactionId SubTransGetParent(TransactionId xid); extern TransactionId SubTransGetTopmostTransaction(TransactionId xid); -extern int SUBTRANSShmemSize(void); +extern Size SUBTRANSShmemSize(void); extern void SUBTRANSShmemInit(void); extern void BootStrapSUBTRANS(void); extern void StartupSUBTRANS(TransactionId oldestActiveXID); diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h index a3d6f1c356..a5e147d573 100644 --- a/src/include/access/twophase.h +++ b/src/include/access/twophase.h @@ -27,7 +27,7 @@ typedef struct GlobalTransactionData *GlobalTransaction; /* GUC variable */ extern int max_prepared_xacts; -extern int TwoPhaseShmemSize(void); +extern Size TwoPhaseShmemSize(void); extern void TwoPhaseShmemInit(void); extern PGPROC *TwoPhaseGetDummyProc(TransactionId xid); diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 96e05c696b..5b7a7c0e03 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -156,7 +156,7 @@ extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record); extern void xlog_desc(char *buf, uint8 xl_info, char *rec); extern void UpdateControlFile(void); -extern int XLOGShmemSize(void); +extern Size XLOGShmemSize(void); extern void XLOGShmemInit(void); extern void BootStrapXLOG(void); extern void StartupXLOG(void); diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 368f1935fa..06aca08d90 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -604,6 +604,9 @@ your system. */ #undef PTHREAD_CREATE_JOINABLE +/* The size of a `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + /* The size of a `unsigned long', as computed by sizeof. */ #undef SIZEOF_UNSIGNED_LONG diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h index 5f4c709bf5..49eabcca40 100644 --- a/src/include/postmaster/bgwriter.h +++ b/src/include/postmaster/bgwriter.h @@ -28,7 +28,7 @@ extern void RequestCheckpoint(bool waitforit, bool warnontime); extern bool ForwardFsyncRequest(RelFileNode rnode, BlockNumber segno); extern void AbsorbFsyncRequests(void); -extern int BgWriterShmemSize(void); +extern Size BgWriterShmemSize(void); extern void BgWriterShmemInit(void); #endif /* _BGWRITER_H */ diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index 4463919419..38b59e4a2d 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -42,7 +42,7 @@ extern void ClosePostmasterPorts(bool am_syslogger); extern pid_t postmaster_forkexec(int argc, char *argv[]); extern int SubPostmasterMain(int argc, char *argv[]); -extern size_t ShmemBackendArraySize(void); +extern Size ShmemBackendArraySize(void); extern void ShmemBackendArrayAllocation(void); #endif diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index dcb711c2c0..b4e634a59c 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -182,11 +182,11 @@ extern long int LocalBufferFlushCount; extern BufferDesc *StrategyGetBuffer(void); extern void StrategyFreeBuffer(BufferDesc *buf, bool at_head); extern int StrategySyncStart(void); -extern int StrategyShmemSize(void); +extern Size StrategyShmemSize(void); extern void StrategyInitialize(bool init); /* buf_table.c */ -extern int BufTableShmemSize(int size); +extern Size BufTableShmemSize(int size); extern void InitBufTable(int size); extern int BufTableLookup(BufferTag *tagPtr); extern int BufTableInsert(BufferTag *tagPtr, int buf_id); diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index f0e169417c..d9516dca78 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -140,7 +140,7 @@ extern void DropBuffers(Oid dbid); #ifdef NOT_USED extern void PrintPinnedBufs(void); #endif -extern int BufferShmemSize(void); +extern Size BufferShmemSize(void); extern RelFileNode BufferGetFileNode(Buffer buffer); extern void SetBufferCommitInfoNeedsSave(Buffer buffer); diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h index 4e04df4eb5..6027826a6b 100644 --- a/src/include/storage/freespace.h +++ b/src/include/storage/freespace.h @@ -37,7 +37,7 @@ extern int MaxFSMPages; * function prototypes */ extern void InitFreeSpaceMap(void); -extern int FreeSpaceShmemSize(void); +extern Size FreeSpaceShmemSize(void); extern BlockNumber GetPageWithFreeSpace(RelFileNode *rel, Size spaceNeeded); extern BlockNumber RecordAndGetPageWithFreeSpace(RelFileNode *rel, diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index 905f5b4d69..2d040b231e 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -391,7 +391,7 @@ extern int LockCheckConflicts(LockMethod lockMethodTable, extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode); extern void GrantAwaitedLock(void); extern void RemoveFromWaitQueue(PGPROC *proc); -extern int LockShmemSize(void); +extern Size LockShmemSize(void); extern bool DeadLockCheck(PGPROC *proc); extern void DeadLockReport(void); extern void RememberSimpleDeadLock(PGPROC *proc1, diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h index d8f3d7ba72..c82bacb017 100644 --- a/src/include/storage/lwlock.h +++ b/src/include/storage/lwlock.h @@ -73,7 +73,7 @@ extern void LWLockReleaseAll(void); extern bool LWLockHeldByMe(LWLockId lockid); extern int NumLWLocks(void); -extern int LWLockShmemSize(void); +extern Size LWLockShmemSize(void); extern void CreateLWLocks(void); #endif /* LWLOCK_H */ diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index cb2ab59a20..6ffd06e1cf 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -29,8 +29,8 @@ typedef struct PGShmemHeader /* standard header for all Postgres shmem */ int32 magic; /* magic # to identify Postgres segments */ #define PGShmemMagic 679834893 pid_t creatorPID; /* PID of creating process */ - uint32 totalsize; /* total size of segment */ - uint32 freeoffset; /* offset to first free space */ + Size totalsize; /* total size of segment */ + Size freeoffset; /* offset to first free space */ #ifndef WIN32 /* Windows doesn't have useful inode#s */ dev_t device; /* device data directory is on */ ino_t inode; /* inode number of data directory */ @@ -45,8 +45,8 @@ extern void *UsedShmemSegAddr; extern void PGSharedMemoryReAttach(void); #endif -extern PGShmemHeader *PGSharedMemoryCreate(uint32 size, bool makePrivate, - int port); +extern PGShmemHeader *PGSharedMemoryCreate(Size size, bool makePrivate, + int port); extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2); extern void PGSharedMemoryDetach(void); diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 7cce7b92ad..1ebd77b94f 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -122,7 +122,7 @@ extern int StatementTimeout; * Function Prototypes */ extern int ProcGlobalSemas(void); -extern int ProcGlobalShmemSize(void); +extern Size ProcGlobalShmemSize(void); extern void InitProcGlobal(void); extern void InitProcess(void); extern void InitDummyProcess(int proctype); diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index cfe86b3289..5cc56c3074 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -17,7 +17,7 @@ #include "storage/lock.h" -extern int ProcArrayShmemSize(void); +extern Size ProcArrayShmemSize(void); extern void CreateSharedProcArray(void); extern void ProcArrayAdd(PGPROC *proc); extern void ProcArrayRemove(PGPROC *proc); diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index c8327d0b45..7949adc158 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -68,7 +68,8 @@ extern void InitShmemIndex(void); extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags); extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); - +extern Size add_size(Size s1, Size s2); +extern Size mul_size(Size s1, Size s2); /* size constants for the shmem index table */ /* max size of data structure string name */ diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h index 9d2dba8857..985df919eb 100644 --- a/src/include/storage/sinval.h +++ b/src/include/storage/sinval.h @@ -83,8 +83,8 @@ typedef union } SharedInvalidationMessage; -extern int SInvalShmemSize(int maxBackends); -extern void CreateSharedInvalidationState(int maxBackends); +extern Size SInvalShmemSize(void); +extern void CreateSharedInvalidationState(void); extern void InitBackendSharedInvalidationState(void); extern void SendSharedInvalidMessage(SharedInvalidationMessage *msg); diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h index 7f16a77109..49ba5487be 100644 --- a/src/include/storage/sinvaladt.h +++ b/src/include/storage/sinvaladt.h @@ -107,7 +107,7 @@ extern SISeg *shmInvalBuffer; /* pointer to the shared inval buffer */ /* * prototypes for functions in sinvaladt.c */ -extern void SIBufferInit(int maxBackends); +extern void SIBufferInit(void); extern int SIBackendInit(SISeg *segP); extern bool SIInsertDataEntry(SISeg *segP, SharedInvalidationMessage *data); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index 3a09d4e1d8..3f53feb8da 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -190,7 +190,7 @@ extern void *hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr); extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp); extern void *hash_seq_search(HASH_SEQ_STATUS *status); -extern long hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size(long num_entries, Size entrysize); extern long hash_select_dirsize(long num_entries); /* |