From 712704d3539e5ed6807e0b46fddaaf8ed47c2403 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 14 Jul 2022 19:23:35 +1200 Subject: [PATCH] Remove redundant ftruncate() for POSIX DSM memory. In early releases of the DSM infrastructure, it was possible to resize segments. That was removed in release 12 by commit 3c60d0fa. Now the ftruncate() + posix_fallocate() sequence during DSM segment creation has a redundant step: we're always extending from zero to the desired size, so we might as well just call posix_fallocate(). Let's also include the remaining ftruncate() call (non-Linux POSIX systems) in the wait event reporting, for good measure. Discussion: https://postgr.es/m/CA%2BhUKGJSm-nq8s%2B_59zb7NbFQF-OS%3DxTnTAiGLrQpuSmU2y_1A%40mail.gmail.com --- src/backend/storage/ipc/dsm_impl.c | 54 ++++++++++++++---------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 33a27b3a45..6f21a75775 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -364,43 +364,39 @@ dsm_impl_posix_resize(int fd, off_t size) */ PG_SETMASK(&BlockSig); - /* Truncate (or extend) the file to the requested size. */ - do - { - rc = ftruncate(fd, size); - } while (rc < 0 && errno == EINTR); - + pgstat_report_wait_start(WAIT_EVENT_DSM_FILL_ZERO_WRITE); +#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__) /* - * 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 + * On Linux, a shm_open fd is backed by a tmpfs file. If we were to use + * ftruncate, the file would 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. + * + * We still use a traditional EINTR retry loop to handle SIGCONT. + * posix_fallocate() doesn't restart automatically, and we don't want + * this to fail if you attach a debugger. */ -#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__) - if (rc == 0) + do { - /* - * We still use a traditional EINTR retry loop to handle SIGCONT. - * posix_fallocate() doesn't restart automatically, and we don't want - * this to fail if you attach a debugger. - */ - pgstat_report_wait_start(WAIT_EVENT_DSM_FILL_ZERO_WRITE); - do - { - rc = posix_fallocate(fd, 0, size); - } while (rc == EINTR); - pgstat_report_wait_end(); + rc = posix_fallocate(fd, 0, size); + } while (rc == EINTR); - /* - * The caller expects errno to be set, but posix_fallocate() doesn't - * set it. Instead it returns error numbers directly. So set errno, - * even though we'll also return rc to indicate success or failure. - */ - errno = rc; - } -#endif /* HAVE_POSIX_FALLOCATE && __linux__ */ + /* + * The caller expects errno to be set, but posix_fallocate() doesn't + * set it. Instead it returns error numbers directly. So set errno, + * even though we'll also return rc to indicate success or failure. + */ + errno = rc; +#else + /* Extend the file to the requested size. */ + do + { + rc = ftruncate(fd, size); + } while (rc < 0 && errno == EINTR); +#endif + pgstat_report_wait_end(); save_errno = errno; PG_SETMASK(&UnBlockSig);