[libc-commits] [libc] [libc] Implement fallocate (PR #222843)

via libc-commits libc-commits at lists.llvm.org
Wed Sep 16 19:20:30 PDT 2026


https://github.com/afnrow updated https://github.com/llvm/llvm-project/pull/222843

>From c5212f15f759b7ed2724136207628458d0fb6c30 Mon Sep 17 00:00:00 2001
From: yahia ahmed <yahia.a.abdrabou at gmail.com>
Date: Fri, 11 Sep 2026 08:12:28 +0300
Subject: [PATCH 1/5] [libc] Implement fallocate

---
 libc/config/linux/aarch64/entrypoints.txt     |  1 +
 libc/config/linux/x86_64/entrypoints.txt      |  1 +
 libc/include/fcntl.yaml                       |  9 +++
 .../llvm-libc-macros/linux/fcntl-macros.h     |  8 +++
 .../linux/syscall_wrappers/CMakeLists.txt     | 14 +++++
 .../OSUtil/linux/syscall_wrappers/fallocate.h | 42 +++++++++++++
 libc/src/fcntl/fallocate.h                    | 26 ++++++++
 libc/src/fcntl/linux/CMakeLists.txt           | 12 ++++
 libc/src/fcntl/linux/fallocate.cpp            | 32 ++++++++++
 libc/test/src/fcntl/CMakeLists.txt            | 16 +++++
 libc/test/src/fcntl/fallocate_test.cpp        | 59 +++++++++++++++++++
 libc/utils/docgen/fcntl.yaml                  |  2 +
 12 files changed, 222 insertions(+)
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
 create mode 100644 libc/src/fcntl/fallocate.h
 create mode 100644 libc/src/fcntl/linux/fallocate.cpp
 create mode 100644 libc/test/src/fcntl/fallocate_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index a63d6ad6282c1f..b8d40e5744547d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -38,6 +38,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # fcntl.h entrypoints
     libc.src.fcntl.creat
+    libc.src.fcntl.fallocate
     libc.src.fcntl.fcntl
     libc.src.fcntl.open
     libc.src.fcntl.openat
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3f4e563e543595..711849cc2bb1f8 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -49,6 +49,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # fcntl.h entrypoints
     libc.src.fcntl.creat
+    libc.src.fcntl.fallocate
     libc.src.fcntl.fcntl
     libc.src.fcntl.open
     libc.src.fcntl.openat
diff --git a/libc/include/fcntl.yaml b/libc/include/fcntl.yaml
index 2b73c8da1e989e..49aac448e7076f 100644
--- a/libc/include/fcntl.yaml
+++ b/libc/include/fcntl.yaml
@@ -40,6 +40,15 @@ functions:
     arguments:
       - type: const char *
       - type: mode_t
+  - name: fallocate
+    standards:
+      - linux
+    return_type: int
+    arguments:
+      - type: int
+      - type: int
+      - type: off_t
+      - type: off_t
   - name: fcntl
     standards:
       - posix
diff --git a/libc/include/llvm-libc-macros/linux/fcntl-macros.h b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
index 648c4a9ec00da6..dc7be0b9045f99 100644
--- a/libc/include/llvm-libc-macros/linux/fcntl-macros.h
+++ b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
@@ -24,6 +24,14 @@
 #define O_SYNC 004010000
 #define O_TRUNC 000001000
 
+#define FALLOC_FL_KEEP_SIZE 0x01
+#define FALLOC_FL_PUNCH_HOLE 0x02
+#define FALLOC_FL_NO_HIDE_STALE 0x04
+#define FALLOC_FL_COLLAPSE_RANGE 0x08
+#define FALLOC_FL_ZERO_RANGE 0x10
+#define FALLOC_FL_INSERT_RANGE 0x20
+#define FALLOC_FL_UNSHARE_RANGE 0x40
+
 #ifdef __aarch64__
 #define O_DIRECT 000200000
 #define O_DIRECTORY 000040000
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 17665f87dfcd84..c24bec607ba52c 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -1303,3 +1303,17 @@ add_header_library(
     libc.src.__support.macros.config
     libc.src.__support.OSUtil.osutil
 )
+
+add_header_library(
+  fallocate
+  HDRS
+    fallocate.h
+  DEPENDS
+    libc.src.__support.macros.config
+    libc.src.__support.common
+    libc.src.__support.OSUtil.osutil
+    libc.include.sys_syscall
+    libc.hdr.types.off_t
+    libc.hdr.errno_macros
+    libc.src.__support.error_or
+)
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
new file mode 100644
index 00000000000000..88cf78cd345d1a
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the declaration of the fallocate, which is the
+/// base syscall wrapper for all fallocate dependent calls.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FALLOCATE_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FALLOCATE_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/types/off_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> fallocate(int fd, int mode, off_t offset, off_t size) {
+#ifdef SYS_fallocate
+#if !__SIZEOF__POINTER == 8 // 64 bit machines
+  /* TODO: Add support for 32 bits */
+  return Error(ENOSYS);
+#else
+  return syscall_checked<int>(SYS_fallocate, fd, mode, offset, size);
+#endif
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+#endif
diff --git a/libc/src/fcntl/fallocate.h b/libc/src/fcntl/fallocate.h
new file mode 100644
index 00000000000000..bfc5605fe8251c
--- /dev/null
+++ b/libc/src/fcntl/fallocate.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for fallocate
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_FCNTL_FALLOCATE_H
+#define LLVM_LIBC_SRC_FCNTL_FALLOCATE_H
+
+#include "src/__support/macros/config.h"
+#include "hdr/types/off_t.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+  int fallocate(int fd, int mode, off_t offset, off_t size);
+
+}
+
+#endif
diff --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt
index e50cc45c9ea7a1..9e20d9947acd6b 100644
--- a/libc/src/fcntl/linux/CMakeLists.txt
+++ b/libc/src/fcntl/linux/CMakeLists.txt
@@ -74,3 +74,15 @@ add_entrypoint_object(
     libc.src.__support.common
     libc.src.__support.macros.config
 )
+
+add_entrypoint_object(
+  fallocate
+  SRCS
+    fallocate.cpp
+  HDRS
+    ../fallocate.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.__support.OSUtil.linux.syscall_wrappers.fallocate
+    libc.hdr.types.off_t
+)
diff --git a/libc/src/fcntl/linux/fallocate.cpp b/libc/src/fcntl/linux/fallocate.cpp
new file mode 100644
index 00000000000000..9237428f017e18
--- /dev/null
+++ b/libc/src/fcntl/linux/fallocate.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the declaration of the fallocate, which is the
+/// fcntl fallocate function for linux.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/fcntl/fallocate.h"
+
+#include "src/__support/OSUtil/linux/syscall_wrappers/fallocate.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/libc_errno.h"
+#include "hdr/types/off_t.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+  LLVM_LIBC_FUNCTION(int, fallocate, (int fd, int mode, off_t offset, off_t size)) {
+    auto result = linux_syscalls::fallocate(fd, mode, offset, size);
+    if (!result.has_value()) {
+      libc_errno = result.error();
+      return -1;
+    }
+    return 0;
+  }
+}
diff --git a/libc/test/src/fcntl/CMakeLists.txt b/libc/test/src/fcntl/CMakeLists.txt
index 6a2acd9578697d..1d952c435468ae 100644
--- a/libc/test/src/fcntl/CMakeLists.txt
+++ b/libc/test/src/fcntl/CMakeLists.txt
@@ -99,3 +99,19 @@ add_libc_test(
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
+
+add_libc_test(
+  fallocate_test
+  SUITE
+    libc_fcntl_unittests
+  SRCS
+    fallocate_test.cpp
+  DEPENDS
+    libc.include.fcntl
+    libc.src.fcntl.fallocate
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.unistd.unlink
+    libc.src.sys.stat.fstat
+    libc.src.__support.libc_errno
+)
diff --git a/libc/test/src/fcntl/fallocate_test.cpp b/libc/test/src/fcntl/fallocate_test.cpp
new file mode 100644
index 00000000000000..62b2258ccdcbe9
--- /dev/null
+++ b/libc/test/src/fcntl/fallocate_test.cpp
@@ -0,0 +1,59 @@
+//===-- Unittests for fallocate -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/fcntl/fallocate.h"
+#include "src/fcntl/open.h"
+#include "src/sys/stat/fstat.h"
+#include "src/unistd/close.h"
+#include "src/unistd/unlink.h"
+#include "src/__support/libc_errno.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(LlvmLibcFallocateTest, BasicAllocate) {
+  constexpr char TEST_FILE[] = "testdata/fallocate_basic.test";
+
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0600);
+  ASSERT_GT(fd, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  // Mode 0: expand file size to offset + len (4096 bytes)
+  ASSERT_THAT(LIBC_NAMESPACE::fallocate(fd, 0, 0, 4096), Succeeds(0));
+
+  struct stat st;
+  ASSERT_EQ(LIBC_NAMESPACE::fstat(fd, &st), 0);
+  ASSERT_EQ(static_cast<off_t>(st.st_size), static_cast<off_t>(4096));
+
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+}
+
+TEST(LlvmLibcFallocateTest, KeepSize) {
+  constexpr char TEST_FILE[] = "testdata/fallocate_keep_size.test";
+
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0600);
+  ASSERT_GT(fd, 0);
+
+  // Pre-allocate space at offset 8192, length 4096, but keep file size at 0
+  ASSERT_THAT(
+      LIBC_NAMESPACE::fallocate(fd, FALLOC_FL_KEEP_SIZE, 8192, 4096),
+      Succeeds(0));
+
+  struct stat st;
+  ASSERT_EQ(LIBC_NAMESPACE::fstat(fd, &st), 0);
+  ASSERT_EQ(static_cast<off_t>(st.st_size), static_cast<off_t>(0));
+
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+}
diff --git a/libc/utils/docgen/fcntl.yaml b/libc/utils/docgen/fcntl.yaml
index 7a6b656cc0a802..f9a9a0fd37e13e 100644
--- a/libc/utils/docgen/fcntl.yaml
+++ b/libc/utils/docgen/fcntl.yaml
@@ -11,6 +11,8 @@ functions:
     in-latest-posix: ''
   posix_fallocate:
     in-latest-posix: ''
+  fallocate:
+    in-latest-posix: ''
 
 macros:
   AT_EACCESS:

>From 7d00dd05a9e3c06894580d727a4dd2d802b530d5 Mon Sep 17 00:00:00 2001
From: yahia ahmed <yahia.a.abdrabou at gmail.com>
Date: Fri, 11 Sep 2026 16:36:12 +0300
Subject: [PATCH 2/5] Fix style issues and address comments

---
 .../llvm-libc-macros/linux/fcntl-macros.h     |  8 -------
 .../linux/syscall_wrappers/CMakeLists.txt     |  2 ++
 .../OSUtil/linux/syscall_wrappers/fallocate.h | 22 ++++++++++++-------
 libc/src/fcntl/fallocate.h                    |  5 ++---
 libc/src/fcntl/linux/fallocate.cpp            | 19 ++++++++--------
 libc/test/src/fcntl/fallocate_test.cpp        | 21 +++++++++---------
 libc/utils/docgen/fcntl.yaml                  |  2 +-
 7 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/libc/include/llvm-libc-macros/linux/fcntl-macros.h b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
index dc7be0b9045f99..648c4a9ec00da6 100644
--- a/libc/include/llvm-libc-macros/linux/fcntl-macros.h
+++ b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
@@ -24,14 +24,6 @@
 #define O_SYNC 004010000
 #define O_TRUNC 000001000
 
-#define FALLOC_FL_KEEP_SIZE 0x01
-#define FALLOC_FL_PUNCH_HOLE 0x02
-#define FALLOC_FL_NO_HIDE_STALE 0x04
-#define FALLOC_FL_COLLAPSE_RANGE 0x08
-#define FALLOC_FL_ZERO_RANGE 0x10
-#define FALLOC_FL_INSERT_RANGE 0x20
-#define FALLOC_FL_UNSHARE_RANGE 0x40
-
 #ifdef __aarch64__
 #define O_DIRECT 000200000
 #define O_DIRECTORY 000040000
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index c24bec607ba52c..4ec311a93e586b 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -1315,5 +1315,7 @@ add_header_library(
     libc.include.sys_syscall
     libc.hdr.types.off_t
     libc.hdr.errno_macros
+    libc.src.__support.CPP.limits
+    libc.src.__support.CPP.bit
     libc.src.__support.error_or
 )
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
index 88cf78cd345d1a..cce4d819aacf4a 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
@@ -17,6 +17,8 @@
 
 #include "hdr/errno_macros.h"
 #include "hdr/types/off_t.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h"
 #include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
 #include "src/__support/common.h"
 #include "src/__support/error_or.h"
@@ -27,14 +29,18 @@ namespace LIBC_NAMESPACE_DECL {
 namespace linux_syscalls {
 
 LIBC_INLINE ErrorOr<int> fallocate(int fd, int mode, off_t offset, off_t size) {
-#ifdef SYS_fallocate
-#if !__SIZEOF__POINTER == 8 // 64 bit machines
-  /* TODO: Add support for 32 bits */
-  return Error(ENOSYS);
-#else
-  return syscall_checked<int>(SYS_fallocate, fd, mode, offset, size);
-#endif
-#endif
+  if constexpr (sizeof(long) == sizeof(uint32_t) &&
+                sizeof(off_t) == sizeof(uint64_t)) {
+    uint64_t offset_bits = cpp::bit_cast<uint64_t>(offset);
+    long offset_low = static_cast<long>(offset_bits & UINT32_MAX);
+    long offset_high = static_cast<long>(offset_bits >> 32);
+    uint64_t len_bits = cpp::bit_cast<uint64_t>(size);
+    long len_low = static_cast<long>(len_bits & UINT32_MAX);
+    long len_high = static_cast<long>(len_bits >> 32);
+    return syscall_checked<int>(SYS_fallocate, fd, mode, offset_low,
+                                offset_high, len_low, len_high);
+  } else
+    return syscall_checked<int>(SYS_fallocate, fd, mode, offset, size);
 }
 
 } // namespace linux_syscalls
diff --git a/libc/src/fcntl/fallocate.h b/libc/src/fcntl/fallocate.h
index bfc5605fe8251c..7dcdc560c37514 100644
--- a/libc/src/fcntl/fallocate.h
+++ b/libc/src/fcntl/fallocate.h
@@ -14,13 +14,12 @@
 #ifndef LLVM_LIBC_SRC_FCNTL_FALLOCATE_H
 #define LLVM_LIBC_SRC_FCNTL_FALLOCATE_H
 
-#include "src/__support/macros/config.h"
 #include "hdr/types/off_t.h"
+#include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-  int fallocate(int fd, int mode, off_t offset, off_t size);
-
+int fallocate(int fd, int mode, off_t offset, off_t size);
 }
 
 #endif
diff --git a/libc/src/fcntl/linux/fallocate.cpp b/libc/src/fcntl/linux/fallocate.cpp
index 9237428f017e18..59361988848eb0 100644
--- a/libc/src/fcntl/linux/fallocate.cpp
+++ b/libc/src/fcntl/linux/fallocate.cpp
@@ -14,19 +14,20 @@
 
 #include "src/fcntl/fallocate.h"
 
+#include "hdr/types/off_t.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/fallocate.h"
-#include "src/__support/macros/config.h"
 #include "src/__support/libc_errno.h"
-#include "hdr/types/off_t.h"
+#include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-  LLVM_LIBC_FUNCTION(int, fallocate, (int fd, int mode, off_t offset, off_t size)) {
-    auto result = linux_syscalls::fallocate(fd, mode, offset, size);
-    if (!result.has_value()) {
-      libc_errno = result.error();
-      return -1;
-    }
-    return 0;
+LLVM_LIBC_FUNCTION(int, fallocate,
+                   (int fd, int mode, off_t offset, off_t size)) {
+  auto result = linux_syscalls::fallocate(fd, mode, offset, size);
+  if (!result.has_value()) {
+    libc_errno = result.error();
+    return -1;
   }
+  return 0;
 }
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/fcntl/fallocate_test.cpp b/libc/test/src/fcntl/fallocate_test.cpp
index 62b2258ccdcbe9..64050dcc61d152 100644
--- a/libc/test/src/fcntl/fallocate_test.cpp
+++ b/libc/test/src/fcntl/fallocate_test.cpp
@@ -6,17 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "hdr/fcntl_macros.h"
+#include "src/__support/CPP/scope.h"
+#include "src/__support/libc_errno.h"
 #include "src/fcntl/fallocate.h"
 #include "src/fcntl/open.h"
 #include "src/sys/stat/fstat.h"
+#include "src/sys/stat/stat.h"
 #include "src/unistd/close.h"
 #include "src/unistd/unlink.h"
-#include "src/__support/libc_errno.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
-#include "test/UnitTest/ErrnoCheckingTest.h"
-#include <fcntl.h>
-#include <sys/stat.h>
 
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
@@ -27,6 +28,10 @@ TEST(LlvmLibcFallocateTest, BasicAllocate) {
   int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0600);
   ASSERT_GT(fd, 0);
   ASSERT_ERRNO_SUCCESS();
+  LIBC_NAMESPACE::cpp::scope_exit cleanup_fd([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  });
 
   // Mode 0: expand file size to offset + len (4096 bytes)
   ASSERT_THAT(LIBC_NAMESPACE::fallocate(fd, 0, 0, 4096), Succeeds(0));
@@ -34,9 +39,6 @@ TEST(LlvmLibcFallocateTest, BasicAllocate) {
   struct stat st;
   ASSERT_EQ(LIBC_NAMESPACE::fstat(fd, &st), 0);
   ASSERT_EQ(static_cast<off_t>(st.st_size), static_cast<off_t>(4096));
-
-  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
 }
 
 TEST(LlvmLibcFallocateTest, KeepSize) {
@@ -46,9 +48,8 @@ TEST(LlvmLibcFallocateTest, KeepSize) {
   ASSERT_GT(fd, 0);
 
   // Pre-allocate space at offset 8192, length 4096, but keep file size at 0
-  ASSERT_THAT(
-      LIBC_NAMESPACE::fallocate(fd, FALLOC_FL_KEEP_SIZE, 8192, 4096),
-      Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::fallocate(fd, FALLOC_FL_KEEP_SIZE, 8192, 4096),
+              Succeeds(0));
 
   struct stat st;
   ASSERT_EQ(LIBC_NAMESPACE::fstat(fd, &st), 0);
diff --git a/libc/utils/docgen/fcntl.yaml b/libc/utils/docgen/fcntl.yaml
index f9a9a0fd37e13e..1053f357901d95 100644
--- a/libc/utils/docgen/fcntl.yaml
+++ b/libc/utils/docgen/fcntl.yaml
@@ -12,7 +12,7 @@ functions:
   posix_fallocate:
     in-latest-posix: ''
   fallocate:
-    in-latest-posix: ''
+    c-definition: ''
 
 macros:
   AT_EACCESS:

>From 09076301343f5dfd15258c5ec8147525d138c554 Mon Sep 17 00:00:00 2001
From: yahia ahmed <yahia.a.abdrabou at gmail.com>
Date: Mon, 14 Sep 2026 17:03:24 +0300
Subject: [PATCH 3/5] address comments

---
 libc/config/linux/riscv/entrypoints.txt       |  1 +
 .../OSUtil/linux/syscall_wrappers/fallocate.h |  3 +-
 libc/src/fcntl/fallocate.h                    |  1 +
 libc/src/fcntl/linux/fallocate.cpp            |  1 +
 libc/test/src/fcntl/CMakeLists.txt            | 18 ++-----
 libc/test/src/fcntl/linux/CMakeLists.txt      | 17 +++++++
 .../src/fcntl/{ => linux}/fallocate_test.cpp  | 48 ++++++++++++++++---
 7 files changed, 66 insertions(+), 23 deletions(-)
 create mode 100644 libc/test/src/fcntl/linux/CMakeLists.txt
 rename libc/test/src/fcntl/{ => linux}/fallocate_test.cpp (53%)

diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index e8180cbb0c70e7..0280725acae489 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -49,6 +49,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # fcntl.h entrypoints
     libc.src.fcntl.creat
+    libc.src.fcntl.fallocate
     libc.src.fcntl.fcntl
     libc.src.fcntl.open
     libc.src.fcntl.openat
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
index cce4d819aacf4a..2d80c7256dec06 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fallocate.h
@@ -39,8 +39,9 @@ LIBC_INLINE ErrorOr<int> fallocate(int fd, int mode, off_t offset, off_t size) {
     long len_high = static_cast<long>(len_bits >> 32);
     return syscall_checked<int>(SYS_fallocate, fd, mode, offset_low,
                                 offset_high, len_low, len_high);
-  } else
+  } else {
     return syscall_checked<int>(SYS_fallocate, fd, mode, offset, size);
+  }
 }
 
 } // namespace linux_syscalls
diff --git a/libc/src/fcntl/fallocate.h b/libc/src/fcntl/fallocate.h
index 7dcdc560c37514..2924637c3a696c 100644
--- a/libc/src/fcntl/fallocate.h
+++ b/libc/src/fcntl/fallocate.h
@@ -20,6 +20,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 int fallocate(int fd, int mode, off_t offset, off_t size);
+
 }
 
 #endif
diff --git a/libc/src/fcntl/linux/fallocate.cpp b/libc/src/fcntl/linux/fallocate.cpp
index 59361988848eb0..21e9c276d500cd 100644
--- a/libc/src/fcntl/linux/fallocate.cpp
+++ b/libc/src/fcntl/linux/fallocate.cpp
@@ -30,4 +30,5 @@ LLVM_LIBC_FUNCTION(int, fallocate,
   }
   return 0;
 }
+
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/fcntl/CMakeLists.txt b/libc/test/src/fcntl/CMakeLists.txt
index 1d952c435468ae..085fda5762704a 100644
--- a/libc/test/src/fcntl/CMakeLists.txt
+++ b/libc/test/src/fcntl/CMakeLists.txt
@@ -100,18 +100,6 @@ add_libc_test(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
-add_libc_test(
-  fallocate_test
-  SUITE
-    libc_fcntl_unittests
-  SRCS
-    fallocate_test.cpp
-  DEPENDS
-    libc.include.fcntl
-    libc.src.fcntl.fallocate
-    libc.src.fcntl.open
-    libc.src.unistd.close
-    libc.src.unistd.unlink
-    libc.src.sys.stat.fstat
-    libc.src.__support.libc_errno
-)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/src/fcntl/linux/CMakeLists.txt b/libc/test/src/fcntl/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..382f8a119d3d17
--- /dev/null
+++ b/libc/test/src/fcntl/linux/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_custom_target(libc_fallocate_unittests)
+
+add_libc_test(
+  fallocate_test
+  SUITE
+    libc_fcntl_unittests
+  SRCS
+    fallocate_test.cpp
+  DEPENDS
+    libc.include.fcntl
+    libc.src.fcntl.fallocate
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.unistd.unlink
+    libc.src.sys.stat.fstat
+    libc.src.__support.libc_errno
+)
diff --git a/libc/test/src/fcntl/fallocate_test.cpp b/libc/test/src/fcntl/linux/fallocate_test.cpp
similarity index 53%
rename from libc/test/src/fcntl/fallocate_test.cpp
rename to libc/test/src/fcntl/linux/fallocate_test.cpp
index 64050dcc61d152..4c0053faa9d797 100644
--- a/libc/test/src/fcntl/fallocate_test.cpp
+++ b/libc/test/src/fcntl/linux/fallocate_test.cpp
@@ -1,10 +1,15 @@
-//===-- Unittests for fallocate -------------------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the tests for the fallocate POSIX functions
+///
+//===----------------------------------------------------------------------===//
 
 #include "hdr/fcntl_macros.h"
 #include "src/__support/CPP/scope.h"
@@ -19,22 +24,24 @@
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
 
+#include <linux/falloc.h>
+
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
 
 TEST(LlvmLibcFallocateTest, BasicAllocate) {
-  constexpr char TEST_FILE[] = "testdata/fallocate_basic.test";
+  constexpr char TEST_FILE[] = "fallocate_basic.test";
 
   int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0600);
-  ASSERT_GT(fd, 0);
   ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
   LIBC_NAMESPACE::cpp::scope_exit cleanup_fd([&] {
     EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
     EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
   });
 
   // Mode 0: expand file size to offset + len (4096 bytes)
-  ASSERT_THAT(LIBC_NAMESPACE::fallocate(fd, 0, 0, 4096), Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::fallocate(fd, 0, 1024, 3072), Succeeds(0));
 
   struct stat st;
   ASSERT_EQ(LIBC_NAMESPACE::fstat(fd, &st), 0);
@@ -42,10 +49,15 @@ TEST(LlvmLibcFallocateTest, BasicAllocate) {
 }
 
 TEST(LlvmLibcFallocateTest, KeepSize) {
-  constexpr char TEST_FILE[] = "testdata/fallocate_keep_size.test";
+  constexpr char TEST_FILE[] = "fallocate_keep_size.test";
 
   int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0600);
+  ASSERT_ERRNO_SUCCESS();
   ASSERT_GT(fd, 0);
+  LIBC_NAMESPACE::cpp::scope_exit cleanup_fd([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  });
 
   // Pre-allocate space at offset 8192, length 4096, but keep file size at 0
   ASSERT_THAT(LIBC_NAMESPACE::fallocate(fd, FALLOC_FL_KEEP_SIZE, 8192, 4096),
@@ -54,7 +66,29 @@ TEST(LlvmLibcFallocateTest, KeepSize) {
   struct stat st;
   ASSERT_EQ(LIBC_NAMESPACE::fstat(fd, &st), 0);
   ASSERT_EQ(static_cast<off_t>(st.st_size), static_cast<off_t>(0));
+}
+
+TEST(LlvmLibcFallocateTest, InvalidFd) {
+  // Passing an invalid file descriptor should fail with EBADF
+  ASSERT_THAT(LIBC_NAMESPACE::fallocate(-1, 0, 0, 4096), Fails(EBADF));
+}
+
+TEST(LlvmLibcFallocateTest, InvalidMode) {
+  constexpr char TEST_FILE[] = "fallocate_invalid_mode.test";
+
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0600);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+  LIBC_NAMESPACE::cpp::scope_exit cleanup_fd([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  });
 
-  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+  // FALLOC_FL_PUNCH_HOLE without FALLOC_FL_KEEP_SIZE must fail with EINVAL
+  ASSERT_EQ(LIBC_NAMESPACE::fallocate(fd, -1, 0, 4096), -1);
+  // Could be any one of those and potentially more depending on the file system
+  ASSERT_TRUE(libc_errno == EINVAL || libc_errno == ENOTSUP ||
+              libc_errno == EOPNOTSUPP);
+  // for the cleanup to work
+  libc_errno = 0;
 }

>From 9143892cce97a74618afef7c9cfc1b3059d65695 Mon Sep 17 00:00:00 2001
From: yahia ahmed <yahia.a.abdrabou at gmail.com>
Date: Wed, 16 Sep 2026 18:35:13 +0300
Subject: [PATCH 4/5] remove extra comment and arrange entrypoints

---
 libc/test/src/fcntl/linux/CMakeLists.txt     | 2 --
 libc/test/src/fcntl/linux/fallocate_test.cpp | 1 -
 2 files changed, 3 deletions(-)

diff --git a/libc/test/src/fcntl/linux/CMakeLists.txt b/libc/test/src/fcntl/linux/CMakeLists.txt
index 382f8a119d3d17..a280fdbac652c4 100644
--- a/libc/test/src/fcntl/linux/CMakeLists.txt
+++ b/libc/test/src/fcntl/linux/CMakeLists.txt
@@ -1,5 +1,3 @@
-add_custom_target(libc_fallocate_unittests)
-
 add_libc_test(
   fallocate_test
   SUITE
diff --git a/libc/test/src/fcntl/linux/fallocate_test.cpp b/libc/test/src/fcntl/linux/fallocate_test.cpp
index 4c0053faa9d797..a7cbb44d011d10 100644
--- a/libc/test/src/fcntl/linux/fallocate_test.cpp
+++ b/libc/test/src/fcntl/linux/fallocate_test.cpp
@@ -84,7 +84,6 @@ TEST(LlvmLibcFallocateTest, InvalidMode) {
     EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
   });
 
-  // FALLOC_FL_PUNCH_HOLE without FALLOC_FL_KEEP_SIZE must fail with EINVAL
   ASSERT_EQ(LIBC_NAMESPACE::fallocate(fd, -1, 0, 4096), -1);
   // Could be any one of those and potentially more depending on the file system
   ASSERT_TRUE(libc_errno == EINVAL || libc_errno == ENOTSUP ||

>From 8dbc0ad8cce641047794369d59f854535626c646 Mon Sep 17 00:00:00 2001
From: yahia ahmed <yahia.a.abdrabou at gmail.com>
Date: Thu, 17 Sep 2026 05:19:36 +0300
Subject: [PATCH 5/5] add fallocate to entrypoints

---
 libc/src/fcntl/CMakeLists.txt       |  7 +++++++
 libc/src/fcntl/linux/CMakeLists.txt | 24 ++++++++++++------------
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/libc/src/fcntl/CMakeLists.txt b/libc/src/fcntl/CMakeLists.txt
index 09afab57b7aa51..99fb047cdc8c3d 100644
--- a/libc/src/fcntl/CMakeLists.txt
+++ b/libc/src/fcntl/CMakeLists.txt
@@ -16,6 +16,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.fcntl
 )
 
+add_entrypoint_object(
+  fallocate
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.fallocate
+)
+
 add_entrypoint_object(
   open
   ALIAS
diff --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt
index 9e20d9947acd6b..fa41eeb1b2f1e8 100644
--- a/libc/src/fcntl/linux/CMakeLists.txt
+++ b/libc/src/fcntl/linux/CMakeLists.txt
@@ -11,6 +11,18 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  fallocate
+  SRCS
+    fallocate.cpp
+  HDRS
+    ../fallocate.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.__support.OSUtil.linux.syscall_wrappers.fallocate
+    libc.hdr.types.off_t
+)
+
 add_entrypoint_object(
   fcntl
   SRCS
@@ -74,15 +86,3 @@ add_entrypoint_object(
     libc.src.__support.common
     libc.src.__support.macros.config
 )
-
-add_entrypoint_object(
-  fallocate
-  SRCS
-    fallocate.cpp
-  HDRS
-    ../fallocate.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.src.__support.OSUtil.linux.syscall_wrappers.fallocate
-    libc.hdr.types.off_t
-)



More information about the libc-commits mailing list