[libc-commits] [libc] 1d471b2 - [libc] Implement posix_fallocate in fcntl (#225475)

via libc-commits libc-commits at lists.llvm.org
Tue Sep 22 12:49:26 PDT 2026


Author: Aman Maurya
Date: 2026-09-22T19:49:16Z
New Revision: 1d471b25430415c26e9a6291b4b1db5542a29864

URL: https://github.com/llvm/llvm-project/commit/1d471b25430415c26e9a6291b4b1db5542a29864
DIFF: https://github.com/llvm/llvm-project/commit/1d471b25430415c26e9a6291b4b1db5542a29864.diff

LOG: [libc] Implement posix_fallocate in fcntl (#225475)

Implement the standard POSIX.1-2008 / POSIX.1-2024 function
`posix_fallocate` in `<fcntl.h>`.

Fixes #225469

Added: 
    libc/src/fcntl/linux/posix_fallocate.cpp
    libc/src/fcntl/posix_fallocate.h
    libc/test/src/fcntl/posix_fallocate_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/fcntl.yaml
    libc/src/fcntl/CMakeLists.txt
    libc/src/fcntl/linux/CMakeLists.txt
    libc/test/src/fcntl/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 48b91033e6fd2..7ddb2d45e9771 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -44,6 +44,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.fcntl.openat
     libc.src.fcntl.posix_fadvise
     libc.src.fcntl.posix_fadvise64
+    libc.src.fcntl.posix_fallocate
 
     # grp.h entrypoints
     libc.src.grp.endgrent

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 54baa8fde0dc5..7c01c536ed73a 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -55,6 +55,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.fcntl.openat
     libc.src.fcntl.posix_fadvise
     libc.src.fcntl.posix_fadvise64
+    libc.src.fcntl.posix_fallocate
 
     # grp.h entrypoints
     libc.src.grp.endgrent

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 28c78f0927f4c..e9761d6da1434 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -55,6 +55,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.fcntl.openat
     libc.src.fcntl.posix_fadvise
     libc.src.fcntl.posix_fadvise64
+    libc.src.fcntl.posix_fallocate
 
     # grp.h entrypoints
     libc.src.grp.endgrent

diff  --git a/libc/include/fcntl.yaml b/libc/include/fcntl.yaml
index 49aac448e7076..849c6247d5786 100644
--- a/libc/include/fcntl.yaml
+++ b/libc/include/fcntl.yaml
@@ -92,3 +92,11 @@ functions:
       - type: off64_t
       - type: off64_t
       - type: int
+  - name: posix_fallocate
+    standards:
+      - posix
+    return_type: int
+    arguments:
+      - type: int
+      - type: off_t
+      - type: off_t

diff  --git a/libc/src/fcntl/CMakeLists.txt b/libc/src/fcntl/CMakeLists.txt
index 99fb047cdc8c3..1ed006e6b24ff 100644
--- a/libc/src/fcntl/CMakeLists.txt
+++ b/libc/src/fcntl/CMakeLists.txt
@@ -50,3 +50,10 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.posix_fadvise64
 )
+
+add_entrypoint_object(
+  posix_fallocate
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.posix_fallocate
+)

diff  --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt
index fa41eeb1b2f1e..09c5f57404695 100644
--- a/libc/src/fcntl/linux/CMakeLists.txt
+++ b/libc/src/fcntl/linux/CMakeLists.txt
@@ -86,3 +86,17 @@ add_entrypoint_object(
     libc.src.__support.common
     libc.src.__support.macros.config
 )
+
+add_entrypoint_object(
+  posix_fallocate
+  SRCS
+    posix_fallocate.cpp
+  HDRS
+    ../posix_fallocate.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.types.off_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.fallocate
+    libc.src.__support.common
+    libc.src.__support.macros.config
+)

diff  --git a/libc/src/fcntl/linux/posix_fallocate.cpp b/libc/src/fcntl/linux/posix_fallocate.cpp
new file mode 100644
index 0000000000000..e8e5103a0eb29
--- /dev/null
+++ b/libc/src/fcntl/linux/posix_fallocate.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Linux implementation of posix_fallocate.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/fcntl/posix_fallocate.h"
+
+#include "hdr/errno_macros.h"
+#include "hdr/types/off_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/fallocate.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, posix_fallocate, (int fd, off_t offset, off_t len)) {
+  if (offset < 0 || len <= 0)
+    return EINVAL;
+
+  auto result = linux_syscalls::fallocate(fd, 0, offset, len);
+  if (!result)
+    return result.error();
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/fcntl/posix_fallocate.h b/libc/src/fcntl/posix_fallocate.h
new file mode 100644
index 0000000000000..c91db361de1a9
--- /dev/null
+++ b/libc/src/fcntl/posix_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 posix_fallocate.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_FCNTL_POSIX_FALLOCATE_H
+#define LLVM_LIBC_SRC_FCNTL_POSIX_FALLOCATE_H
+
+#include "hdr/types/off_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int posix_fallocate(int fd, off_t offset, off_t len);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_FCNTL_POSIX_FALLOCATE_H

diff  --git a/libc/test/src/fcntl/CMakeLists.txt b/libc/test/src/fcntl/CMakeLists.txt
index 085fda5762704..4e8b120ec6a70 100644
--- a/libc/test/src/fcntl/CMakeLists.txt
+++ b/libc/test/src/fcntl/CMakeLists.txt
@@ -100,6 +100,29 @@ add_libc_test(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_test(
+  posix_fallocate_test
+  SUITE
+    libc_fcntl_unittests
+  SRCS
+    posix_fallocate_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fcntl_macros
+    libc.hdr.sys_stat_macros
+    libc.hdr.types.off_t
+    libc.hdr.types.struct_stat
+    libc.src.__support.CPP.scope
+    libc.src.fcntl.open
+    libc.src.fcntl.posix_fallocate
+    libc.src.sys.stat.fstat
+    libc.src.unistd.close
+    libc.src.unistd.pipe
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
   add_subdirectory(${LIBC_TARGET_OS})
 endif()

diff  --git a/libc/test/src/fcntl/posix_fallocate_test.cpp b/libc/test/src/fcntl/posix_fallocate_test.cpp
new file mode 100644
index 0000000000000..079c7622754a9
--- /dev/null
+++ b/libc/test/src/fcntl/posix_fallocate_test.cpp
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for posix_fallocate.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_stat_macros.h"
+#include "hdr/types/off_t.h"
+#include "hdr/types/struct_stat.h"
+#include "src/__support/CPP/scope.h"
+#include "src/fcntl/open.h"
+#include "src/fcntl/posix_fallocate.h"
+#include "src/sys/stat/fstat.h"
+#include "src/unistd/close.h"
+#include "src/unistd/pipe.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcPosixFallocateTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST_F(LlvmLibcPosixFallocateTest, InvalidArgs) {
+  // Negative offset must return EINVAL.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(0, -1, 1024), EINVAL);
+  // Zero length may return EINVAL.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(0, 0, 0), EINVAL);
+  // Negative length must return EINVAL.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(0, 0, -1), EINVAL);
+  // posix_fallocate must return error directly and not set errno.
+  ASSERT_ERRNO_SUCCESS();
+}
+
+TEST_F(LlvmLibcPosixFallocateTest, BadFileDescriptor) {
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(-1, 0, 4096), EBADF);
+}
+
+TEST_F(LlvmLibcPosixFallocateTest, AllocateAndExtend) {
+  auto TEST_FILE = libc_make_test_file_path("posix_fallocate_alloc.test");
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+  });
+
+  // Allocate 4096 bytes at offset 0.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(fd, 0, 4096), 0);
+  struct stat st;
+  ASSERT_THAT(LIBC_NAMESPACE::fstat(fd, &st), Succeeds(0));
+  ASSERT_EQ(st.st_size, static_cast<off_t>(4096));
+
+  // Extend allocation further by 2048 bytes at offset 4096.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(fd, 4096, 2048), 0);
+  ASSERT_THAT(LIBC_NAMESPACE::fstat(fd, &st), Succeeds(0));
+  ASSERT_EQ(st.st_size, static_cast<off_t>(6144));
+
+  // Allocation within already allocated range should succeed without changing
+  // size.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(fd, 1024, 1024), 0);
+  ASSERT_THAT(LIBC_NAMESPACE::fstat(fd, &st), Succeeds(0));
+  ASSERT_EQ(st.st_size, static_cast<off_t>(6144));
+}
+
+TEST_F(LlvmLibcPosixFallocateTest, NonZeroOffsetStart) {
+  auto TEST_FILE = libc_make_test_file_path("posix_fallocate_offset.test");
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+  });
+
+  // Pre-allocate space starting at offset 1024 with length 3072 -> size should
+  // become 4096.
+  EXPECT_EQ(LIBC_NAMESPACE::posix_fallocate(fd, 1024, 3072), 0);
+  struct stat st;
+  ASSERT_THAT(LIBC_NAMESPACE::fstat(fd, &st), Succeeds(0));
+  ASSERT_EQ(st.st_size, static_cast<off_t>(4096));
+}
+
+TEST_F(LlvmLibcPosixFallocateTest, Pipe) {
+  int pipefd[2];
+  ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds(0));
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds(0));
+  });
+
+  // fallocate on a pipe should fail with ESPIPE or EBADF (Linux kernel
+  // behavior).
+  int ret = LIBC_NAMESPACE::posix_fallocate(pipefd[1], 0, 1024);
+  EXPECT_TRUE(ret == ESPIPE || ret == EBADF);
+}


        


More information about the libc-commits mailing list