* [PATCH 0/2] nolibc: Add fallocate()
@ 2026-04-15 14:32 Daniel Palmer
2026-04-15 14:32 ` [PATCH 1/2] tools/nolibc: fcntl: " Daniel Palmer
2026-04-15 14:32 ` [PATCH 2/2] selftests/nolibc: Add a very basic test for fallocate() Daniel Palmer
0 siblings, 2 replies; 5+ messages in thread
From: Daniel Palmer @ 2026-04-15 14:32 UTC (permalink / raw)
To: w, linux; +Cc: linux-kernel, Daniel Palmer
While poking around with my "static PIE for nommu" series I found
I needed fallocate(). Implementing it turned out a bit more
interesting than I thought it would be due to how the offset and
size need to be passed on 32bit machines.
I have ran the tests on m68k, arm, arm64, riscv[32|64], x86_64,
i386, x32. I probably missed something, maybe there is a better
way to do this. Maybe it can't actually pass an offset or size
>4GB on x32?
Daniel Palmer (2):
tools/nolibc: fcntl: Add fallocate()
selftests/nolibc: Add a very basic test for fallocate()
tools/include/nolibc/fcntl.h | 30 ++++++++++++++++++
tools/testing/selftests/nolibc/nolibc-test.c | 33 ++++++++++++++++++++
2 files changed, 63 insertions(+)
--
2.51.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] tools/nolibc: fcntl: Add fallocate()
2026-04-15 14:32 [PATCH 0/2] nolibc: Add fallocate() Daniel Palmer
@ 2026-04-15 14:32 ` Daniel Palmer
2026-04-15 15:56 ` Thomas Weißschuh
2026-04-15 14:32 ` [PATCH 2/2] selftests/nolibc: Add a very basic test for fallocate() Daniel Palmer
1 sibling, 1 reply; 5+ messages in thread
From: Daniel Palmer @ 2026-04-15 14:32 UTC (permalink / raw)
To: w, linux; +Cc: linux-kernel, Daniel Palmer
Add fallocate(), some special care is needed to
put the offset and size into the syscall parameters
for 32bit machines and for x32.
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
tools/include/nolibc/fcntl.h | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/tools/include/nolibc/fcntl.h b/tools/include/nolibc/fcntl.h
index ed2f5553c65a..0ebfdb7bc792 100644
--- a/tools/include/nolibc/fcntl.h
+++ b/tools/include/nolibc/fcntl.h
@@ -66,4 +66,34 @@ int open(const char *path, int flags, ...)
return __sysret(_sys_open(path, flags, mode));
}
+/*
+ * int fallocate(int fd, int mode, off_t offset, off_t size);
+ */
+
+#define __NOLIBC_LLARGPART(_arg, _part) \
+ (((union { long long ll; long l[2]; }) { .ll = _arg }).l[_part])
+
+static __attribute__((unused))
+int sys_fallocate(int fd, int mode, off_t offset, off_t size)
+{
+#if defined(__x86_64__) && defined(__ILP32__)
+ const bool offsetsz_two_args = false;
+#else
+ const bool offsetsz_two_args = sizeof(long) != sizeof(off_t);
+#endif
+
+ if (offsetsz_two_args)
+ return __nolibc_syscall6(__NR_fallocate, fd, mode,
+ __NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1),
+ __NOLIBC_LLARGPART(size, 0), __NOLIBC_LLARGPART(size, 1));
+ else
+ return __nolibc_syscall4(__NR_fallocate, fd, mode, offset, size);
+}
+
+static __attribute__((unused))
+int fallocate(int fd, int mode, off_t offset, off_t size)
+{
+ return __sysret(sys_fallocate(fd, mode, offset, size));
+}
+
#endif /* _NOLIBC_FCNTL_H */
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] selftests/nolibc: Add a very basic test for fallocate()
2026-04-15 14:32 [PATCH 0/2] nolibc: Add fallocate() Daniel Palmer
2026-04-15 14:32 ` [PATCH 1/2] tools/nolibc: fcntl: " Daniel Palmer
@ 2026-04-15 14:32 ` Daniel Palmer
2026-04-15 15:59 ` Thomas Weißschuh
1 sibling, 1 reply; 5+ messages in thread
From: Daniel Palmer @ 2026-04-15 14:32 UTC (permalink / raw)
To: w, linux; +Cc: linux-kernel, Daniel Palmer
Create a tmp file, fallocate() to make it a bit bigger, check the
size is what was expected.
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
tools/testing/selftests/nolibc/nolibc-test.c | 33 ++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index d3c4facb54c0..066f436561e7 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -896,6 +896,38 @@ int test_getpagesize(void)
return !c;
}
+int test_fallocate(void)
+{
+ struct stat st;
+ int fd, r;
+
+ /* Create a new tmp file */
+ fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
+ if (fd == -1)
+ return -1;
+
+ /* Expand it to 42 bytes */
+ r = fallocate(fd, 0, 0, 42);
+ if (r)
+ goto close_tmpfile;
+
+ /* Get the new stat */
+ r = fstat(fd, &st);
+ if (r)
+ goto close_tmpfile;
+
+ /* It should be 42 bytes long */
+ if (st.st_size != 42) {
+ r = -1;
+ goto close_tmpfile;
+ }
+
+close_tmpfile:
+ close(fd);
+
+ return r;
+}
+
int test_file_stream(void)
{
FILE *f;
@@ -1442,6 +1474,7 @@ int run_syscall(int min, int max)
CASE_TEST(dup3_0); tmp = dup3(0, 100, 0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
CASE_TEST(dup3_m1); tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break;
+ CASE_TEST(fallocate); EXPECT_SYSZR(1, test_fallocate()); break;
CASE_TEST(fchdir_stdin); EXPECT_SYSER(1, fchdir(STDIN_FILENO), -1, ENOTDIR); break;
CASE_TEST(fchdir_badfd); EXPECT_SYSER(1, fchdir(-1), -1, EBADF); break;
CASE_TEST(file_stream); EXPECT_SYSZR(1, test_file_stream()); break;
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] tools/nolibc: fcntl: Add fallocate()
2026-04-15 14:32 ` [PATCH 1/2] tools/nolibc: fcntl: " Daniel Palmer
@ 2026-04-15 15:56 ` Thomas Weißschuh
0 siblings, 0 replies; 5+ messages in thread
From: Thomas Weißschuh @ 2026-04-15 15:56 UTC (permalink / raw)
To: Daniel Palmer; +Cc: w, linux-kernel
Hi Daniel!
thanks for the patches.
On 2026-04-15 23:32:24+0900, Daniel Palmer wrote:
> Add fallocate(), some special care is needed to
> put the offset and size into the syscall parameters
> for 32bit machines and for x32.
>
> Signed-off-by: Daniel Palmer <daniel@thingy.jp>
> ---
> tools/include/nolibc/fcntl.h | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/tools/include/nolibc/fcntl.h b/tools/include/nolibc/fcntl.h
> index ed2f5553c65a..0ebfdb7bc792 100644
> --- a/tools/include/nolibc/fcntl.h
> +++ b/tools/include/nolibc/fcntl.h
> @@ -66,4 +66,34 @@ int open(const char *path, int flags, ...)
> return __sysret(_sys_open(path, flags, mode));
> }
>
> +/*
> + * int fallocate(int fd, int mode, off_t offset, off_t size);
> + */
> +
> +#define __NOLIBC_LLARGPART(_arg, _part) \
> + (((union { long long ll; long l[2]; }) { .ll = _arg }).l[_part])
This should go into sys.h, as it is fairly generic.
> +static __attribute__((unused))
> +int sys_fallocate(int fd, int mode, off_t offset, off_t size)
This should be _sys_fallocate() to avoid clashing with user symbols.
> +{
> +#if defined(__x86_64__) && defined(__ILP32__)
> + const bool offsetsz_two_args = false;
> +#else
> + const bool offsetsz_two_args = sizeof(long) != sizeof(off_t);
> +#endif
We try to avoid architecture-specific logic in the generic files.
x32 would be covered with sizeof(__kernel_long_t). But MIPS N32 is also
detected incorrectly here. In my opinion the best solution would be to
have an override mechansim like for _sys_mmap and override it for x32
and N32 in arch-x86.h and arch-mips.h.
Maybe also look at the recent proposal for ftruncate() which is somewhat
related:
https://git.kernel.org/pub/scm/linux/kernel/git/thomas.weissschuh/linux.git/commit/?h=b4/nolibc-ftruncate
https://lore.kernel.org/lkml/20260303010039.2969125-2-jordanrichards@google.com/
> +
> + if (offsetsz_two_args)
> + return __nolibc_syscall6(__NR_fallocate, fd, mode,
> + __NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1),
> + __NOLIBC_LLARGPART(size, 0), __NOLIBC_LLARGPART(size, 1));
> + else
> + return __nolibc_syscall4(__NR_fallocate, fd, mode, offset, size);
> +}
> +
> +static __attribute__((unused))
> +int fallocate(int fd, int mode, off_t offset, off_t size)
> +{
> + return __sysret(sys_fallocate(fd, mode, offset, size));
> +}
> +
> #endif /* _NOLIBC_FCNTL_H */
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] selftests/nolibc: Add a very basic test for fallocate()
2026-04-15 14:32 ` [PATCH 2/2] selftests/nolibc: Add a very basic test for fallocate() Daniel Palmer
@ 2026-04-15 15:59 ` Thomas Weißschuh
0 siblings, 0 replies; 5+ messages in thread
From: Thomas Weißschuh @ 2026-04-15 15:59 UTC (permalink / raw)
To: Daniel Palmer; +Cc: w, linux-kernel
On 2026-04-15 23:32:25+0900, Daniel Palmer wrote:
> Create a tmp file, fallocate() to make it a bit bigger, check the
> size is what was expected.
>
> Signed-off-by: Daniel Palmer <daniel@thingy.jp>
> ---
> tools/testing/selftests/nolibc/nolibc-test.c | 33 ++++++++++++++++++++
> 1 file changed, 33 insertions(+)
>
> diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> index d3c4facb54c0..066f436561e7 100644
> --- a/tools/testing/selftests/nolibc/nolibc-test.c
> +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> @@ -896,6 +896,38 @@ int test_getpagesize(void)
> return !c;
> }
>
> +int test_fallocate(void)
> +{
> + struct stat st;
> + int fd, r;
> +
> + /* Create a new tmp file */
> + fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
> + if (fd == -1)
> + return -1;
> +
> + /* Expand it to 42 bytes */
> + r = fallocate(fd, 0, 0, 42);
> + if (r)
> + goto close_tmpfile;
> +
> + /* Get the new stat */
> + r = fstat(fd, &st);
> + if (r)
> + goto close_tmpfile;
> +
> + /* It should be 42 bytes long */
> + if (st.st_size != 42) {
> + r = -1;
> + goto close_tmpfile;
> + }
This should also check that full 64-bit values are passed through.
> +
> +close_tmpfile:
> + close(fd);
> +
> + return r;
> +}
(...)
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-15 15:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-15 14:32 [PATCH 0/2] nolibc: Add fallocate() Daniel Palmer
2026-04-15 14:32 ` [PATCH 1/2] tools/nolibc: fcntl: " Daniel Palmer
2026-04-15 15:56 ` Thomas Weißschuh
2026-04-15 14:32 ` [PATCH 2/2] selftests/nolibc: Add a very basic test for fallocate() Daniel Palmer
2026-04-15 15:59 ` Thomas Weißschuh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox