Bootstrapped and regtested on x86_64-pc-linux-gnu, and also on
x86_64-unknown-freebsd13.3 by Gerald ([1], see also the discussion on
the PR); OK for trunk?

[1]: https://gcc.gnu.org/pipermail/gcc-testresults/2024-December/833487.html
 
-- >8 --

Depending on the libc and filesystem, in cases where posix_fallocate
cannot do an efficient preallocation it may return EINVAL.  In such a
case we should fall back to ftruncate instead.

Apparently, depending on the system the use of posix_fallocate can have
a noticeable speedup over ftruncate in general (depending on the system)
so it probably isn't worth it to use ftruncate in all cases.

        PR c++/100358
        PR c++/115008

gcc/cp/ChangeLog:

        * module.cc (elf_out::create_mapping): Fallback to ftruncate if
        posix_fallocate fails.

Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
---
 gcc/cp/module.cc | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index b9cf16433b5..9ad587ebd6a 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -1905,13 +1905,23 @@ elf_in::begin (location_t loc)
 void
 elf_out::create_mapping (unsigned ext, bool extending)
 {
-#ifndef HAVE_POSIX_FALLOCATE
-#define posix_fallocate(fd,off,len) ftruncate (fd, off + len)
+  /* A wrapper around posix_fallocate, falling back to ftruncate
+     if the underlying filesystem does not support the operation.  */
+  auto allocate = [](int fd, off_t offset, off_t length)
+    {
+#ifdef HAVE_POSIX_FALLOCATE
+      int result = posix_fallocate (fd, offset, length);
+      if (result != EINVAL)
+       return result == 0;
+      /* Not supported by the underlying filesystem, fallback to ftruncate.  */
 #endif
+      return ftruncate (fd, offset + length) == 0;
+    };
+
   void *mapping = MAP_FAILED;
   if (extending && ext < 1024 * 1024)
     {
-      if (!posix_fallocate (fd, offset, ext * 2))
+      if (allocate (fd, offset, ext * 2))
        mapping = mmap (NULL, ext * 2, PROT_READ | PROT_WRITE,
                        MAP_SHARED, fd, offset);
       if (mapping != MAP_FAILED)
@@ -1919,7 +1929,7 @@ elf_out::create_mapping (unsigned ext, bool extending)
     }
   if (mapping == MAP_FAILED)
     {
-      if (!extending || !posix_fallocate (fd, offset, ext))
+      if (!extending || allocate (fd, offset, ext))
        mapping = mmap (NULL, ext, PROT_READ | PROT_WRITE,
                        MAP_SHARED, fd, offset);
       if (mapping == MAP_FAILED)
@@ -1929,7 +1939,6 @@ elf_out::create_mapping (unsigned ext, bool extending)
          ext = 0;
        }
     }
-#undef posix_fallocate
   hdr.buffer = (char *)mapping;
   extent = ext;
 }
-- 
2.47.0

Reply via email to