public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [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