[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