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
 
