diff --git a/configure b/configure
index 84faf6af3eeee194e0e9da829520211cc7048ba9..85cf0e1b1d47b3f44dcb1b14f7ae995c8b5b00ba 100755
--- a/configure
+++ b/configure
@@ -13024,7 +13024,7 @@ fi
 LIBS_including_readline="$LIBS"
 LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
 
-for ac_func in cbrt clock_gettime 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 clock_gettime 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 f6fcacc89c95de893b8e81e50e2b84910487d9b6..aa7d67165d88f5ad3dc590bbb8819afe70ccfde2 100644
--- a/configure.in
+++ b/configure.in
@@ -1430,7 +1430,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 clock_gettime 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 clock_gettime 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 1500465d31cf8691c63ba094200c66e103f5bf9f..4c1addc77c5240f00c04e928dadb040c15d78605 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -73,6 +73,7 @@
 static bool dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 			   void **impl_private, void **mapped_address,
 			   Size *mapped_size, int elevel);
+static int	dsm_impl_posix_resize(int fd, off_t size);
 #endif
 #ifdef USE_DSM_SYSV
 static bool dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
@@ -319,7 +320,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 &&
+			 dsm_impl_posix_resize(fd, request_size) != 0)
 	{
 		int			save_errno;
 
@@ -392,7 +394,55 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 
 	return true;
 }
-#endif
+
+/*
+ * Set the size of a virtual memory region associated with a file descriptor.
+ * If necessary, also 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
+dsm_impl_posix_resize(int fd, off_t size)
+{
+	int			rc;
+
+	/* Truncate (or extend) the file to the requested size. */
+	rc = ftruncate(fd, size);
+
+	/*
+	 * On Linux, a shm_open fd is backed by a tmpfs file.  After resizing with
+	 * ftruncate, the file may contain a hole.  Accessing memory backed by a
+	 * hole causes tmpfs to allocate pages, which fails with SIGBUS if there
+	 * is no more tmpfs space available.  So we ask tmpfs to allocate pages
+	 * here, so we can fail gracefully with ENOSPC now rather than risking
+	 * SIGBUS later.
+	 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+	if (rc == 0)
+	{
+		/* We may get interrupted, if so just retry. */
+		do
+		{
+			rc = posix_fallocate(fd, 0, size);
+		} while (rc == -1 && errno == EINTR);
+
+		if (rc != 0 && errno == ENOSYS)
+		{
+			/*
+			 * Kernel too old (< 2.6.23).  Rather than fail, just trust that
+			 * we won't hit the problem (it typically doesn't show up without
+			 * many-GB-sized requests, anyway).
+			 */
+			rc = 0;
+		}
+	}
+#endif							/* HAVE_POSIX_FALLOCATE && __linux__ */
+
+	return rc;
+}
+
+#endif							/* USE_DSM_POSIX */
 
 #ifdef USE_DSM_SYSV
 /*
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 579d195663c8a1a4c408ee1092324ed6deb25e2a..c65dd7db21504901b6f8d25c3a7f4c5caff96763 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -393,6 +393,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
 
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index 91db0ddd38cbc061a8ed9615f4e21994cfcdeb80..a0bdcbda4ebf3b1d05aa3c1685cde8f83716eb9b 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -261,6 +261,9 @@
 /* Define to 1 if you have the <poll.h> header file. */
 /* #undef HAVE_POLL_H */
 
+/* Define to 1 if you have the `posix_fallocate' function. */
+/* #undef HAVE_POSIX_FALLOCATE */
+
 /* Define to 1 if you have the `pstat' function. */
 /* #undef HAVE_PSTAT */