diff --git a/configure b/configure index 7244c75..22519de 100755 --- a/configure +++ b/configure @@ -12473,7 +12473,7 @@ fi LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l +for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.in b/configure.in index 598fbd8..4346f95 100644 --- a/configure.in +++ b/configure.in @@ -1446,7 +1446,7 @@ PGAC_FUNC_WCSTOMBS_L LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l]) +AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l]) AC_REPLACE_FUNCS(fseeko) case $host_os in diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 173b982..d6c9e95 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -90,6 +90,9 @@ static bool dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, Size *mapped_size, int elevel); #endif static int errcode_for_dynamic_shared_memory(void); +#ifndef USE_DSM_WINDOWS +static int resize_and_allocate(int fd, off_t size); +#endif const struct config_enum_entry dynamic_shared_memory_options[] = { #ifdef USE_DSM_POSIX @@ -319,7 +322,8 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size, } request_size = st.st_size; } - else if (*mapped_size != request_size && ftruncate(fd, request_size)) + else if (*mapped_size != request_size && + resize_and_allocate(fd, request_size)) { int save_errno; @@ -1034,3 +1038,39 @@ errcode_for_dynamic_shared_memory(void) else return errcode_for_file_access(); } + +#ifndef USE_DSM_WINDOWS +/* + * Set the size of a virtual memory region associate with a file descriptor. + * If possible, ensure that virtual memory is actually allocated by the + * operating system to avoid nasty surprises later. + * + * Returns non-zero if either truncation or allocation fails, and sets errno. + */ +static int +resize_and_allocate(int fd, off_t size) +{ + int rc; + + /* Truncate (or extend) the file to the requested size. */ + rc = ftruncate(fd, size); + +#if HAVE_POSIX_FALLOCATE + /* + * Depending on the underlying filesystem, truncating might have + * created a 'hole' in the file. This happens on Linux when the file + * descriptor represents a POSIX shmem segment backed by tmpfs. On + * such systems, it is better to get an ENOSPC error here, rather + * than succeeding here but getting a SIGBUS later when the memory is + * accessed. + */ + if (rc == 0) + { + rc = posix_fallocate(fd, 0, size); + errno = rc; + } +#endif + + return rc; +} +#endif diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index b621ff2..45fc73a 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -379,6 +379,9 @@ /* Define to 1 if you have the `posix_fadvise' function. */ #undef HAVE_POSIX_FADVISE +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ #undef HAVE_PPC_LWARX_MUTEX_HINT