linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: "Thomas Weißschuh" <linux@weissschuh.net>
To: Jordan Richards <jordanrichards@google.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>,
	 Mike Rapoport <rppt@kernel.org>,
	Pratyush Yadav <pratyush@kernel.org>,
	 Shuah Khan <shuah@kernel.org>, Willy Tarreau <w@1wt.eu>,
	Jason Miu <jasonmiu@google.com>,
	 David Matlack <dmatlack@google.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	 linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v3 1/2] tools/nolibc: add ftruncate()
Date: Tue, 3 Mar 2026 08:09:33 +0100	[thread overview]
Message-ID: <c65fdf06-2f69-4c81-be21-a14229eaf1b6@t-8ch.de> (raw)
In-Reply-To: <20260303010039.2969125-2-jordanrichards@google.com>

Hi Jordan,

On 2026-03-03 01:00:38+0000, Jordan Richards wrote:
> On architectures with 32-bit longs, call the compat syscall
> __NR_ftruncate64. As off_t is 64-bit it must be split into 2 registers.
> Unlike llseek() which passes the high and low parts in explicitly named
> arguments, the order here is endian independent.
> 
> Some architectures (arm, mips, ppc) require this pair of registers to
> be aligned to an even register, so add custom sys_ftruncate64 wrappers
> for those.
> 
> A test case for ftruncate is added which validates negative length or
> invalid fd return the appropriate error, and checks the length is
> correct on success.

Thanks, this all looks good in general.

In nolibc-next we renamed all the my_syscall*() functions to
__nolibc_syscall*(), merging this patch through the liveupdate tree
will lead to semantic conflicts.

I see different ways to handle this:
* An an immutable branch to merge into the liveupdate tree
* Split up the series
  * Use raw syscall(__NR_ftruncate) in the liveupdate
    selftests, as it is sufficient for that.
  * Merge the nolibc bits through the nolibc tree.
  * Next cycle, switch to proper nolibc ftruncate().
  * Let Linus handle the conflict when merging the tree.

There are some nitpicks inline, but we can also fix those up when
applying the patch.

> Signed-off-by: Jordan Richards <jordanrichards@google.com>
> ---
>  tools/include/nolibc/arch-arm.h              | 11 +++++
>  tools/include/nolibc/arch-mips.h             | 11 +++++
>  tools/include/nolibc/arch-powerpc.h          | 11 +++++
>  tools/include/nolibc/unistd.h                | 35 ++++++++++++++
>  tools/testing/selftests/nolibc/nolibc-test.c | 51 ++++++++++++++++++++
>  5 files changed, 119 insertions(+)
> 
> diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h
> index 251c42579028..ed65fb674e61 100644
> --- a/tools/include/nolibc/arch-arm.h
> +++ b/tools/include/nolibc/arch-arm.h
> @@ -6,9 +6,11 @@
>  
>  #ifndef _NOLIBC_ARCH_ARM_H
>  #define _NOLIBC_ARCH_ARM_H

Nit: keep an empty line after the include guards.

> +#include <linux/unistd.h>
>  #include "compiler.h"
>  #include "crt.h"
> +#include "std.h"
>  
>  /* Syscalls for ARM in ARM or Thumb modes :
>   *   - registers are 32-bit
> @@ -196,4 +198,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
>  }
>  #endif /* NOLIBC_NO_RUNTIME */
>  
> +#ifdef __NR_ftruncate64

Should be unnecessary.

> +static __attribute__((unused))
> +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
> +{
> +	return my_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
> +}
> +#define sys_ftruncate64 sys_ftruncate64
> +#endif
> +
>  #endif /* _NOLIBC_ARCH_ARM_H */
> diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
> index a72506ceec6b..26d044004ec6 100644
> --- a/tools/include/nolibc/arch-mips.h
> +++ b/tools/include/nolibc/arch-mips.h
> @@ -6,9 +6,11 @@
>  
>  #ifndef _NOLIBC_ARCH_MIPS_H
>  #define _NOLIBC_ARCH_MIPS_H

Also an empty line.

> +#include <linux/unistd.h>
>  #include "compiler.h"
>  #include "crt.h"
> +#include "std.h"
>  
>  #if !defined(_ABIO32) && !defined(_ABIN32) && !defined(_ABI64)
>  #error Unsupported MIPS ABI
> @@ -269,4 +271,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __
>  }
>  #endif /* NOLIBC_NO_RUNTIME */
>  
> +#ifdef __NR_ftruncate64
> +static __attribute__((unused))
> +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
> +{
> +	return my_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
> +}
> +#define sys_ftruncate64 sys_ftruncate64
> +#endif
> +
>  #endif /* _NOLIBC_ARCH_MIPS_H */
> diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h
> index e0c7e0b81f7c..71829cb027e8 100644
> --- a/tools/include/nolibc/arch-powerpc.h
> +++ b/tools/include/nolibc/arch-powerpc.h
> @@ -6,9 +6,11 @@
>  
>  #ifndef _NOLIBC_ARCH_POWERPC_H
>  #define _NOLIBC_ARCH_POWERPC_H
> +#include <linux/unistd.h>
>  
>  #include "compiler.h"
>  #include "crt.h"
> +#include "std.h"
>  
>  /* Syscalls for PowerPC :
>   *   - stack is 16-byte aligned
> @@ -218,4 +220,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
>  }
>  #endif /* NOLIBC_NO_RUNTIME */
>  
> +#ifdef __NR_ftruncate64
> +static __attribute__((unused))
> +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
> +{
> +	return my_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
> +}
> +#define sys_ftruncate64 sys_ftruncate64
> +#endif
> +
>  #endif /* _NOLIBC_ARCH_POWERPC_H */
> diff --git a/tools/include/nolibc/unistd.h b/tools/include/nolibc/unistd.h
> index bb5e80f3f05d..85ac253f9189 100644
> --- a/tools/include/nolibc/unistd.h
> +++ b/tools/include/nolibc/unistd.h
> @@ -48,6 +48,41 @@ int access(const char *path, int amode)
>  	return faccessat(AT_FDCWD, path, amode, 0);
>  }
>  
> +#if !defined(sys_ftruncate64) && defined(__NR_ftruncate64)
> +static __attribute__((unused))
> +int sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
> +{
> +

Nit: Spurious empty line.

> +	return my_syscall3(__NR_ftruncate64, fd, length0, length1);
> +}
> +#define sys_ftruncate64 sys_ftruncate64
> +#endif
> +
> +static __attribute__((unused))
> +int sys_ftruncate(int fd, off_t length)
> +{
> +#ifdef sys_ftruncate64
> +	union {
> +		off_t length;
> +		struct {
> +			uint32_t length0;
> +			uint32_t length1;
> +		};
> +	} arg;
> +
> +	arg.length = length;
> +
> +	return sys_ftruncate64(fd, arg.length0, arg.length1);
> +#else
> +	return my_syscall2(__NR_ftruncate, fd, length);
> +#endif
> +}
> +
> +static __attribute__((unused))
> +int ftruncate(int fd, off_t length)
> +{
> +	return __sysret(sys_ftruncate(fd, length));
> +}
>  
>  static __attribute__((unused))
>  int msleep(unsigned int msecs)
> diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> index 1b9d3b2e2491..6a84dfbb4b73 100644
> --- a/tools/testing/selftests/nolibc/nolibc-test.c
> +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> @@ -969,6 +969,56 @@ int test_fork(enum fork_type type)
>  	}
>  }
>  
> +int test_ftruncate(void)
> +{
> +	int ret;
> +	int fd;
> +	struct stat stat_buf;
> +	const char *filename = "/tmp/ftruncate_test";
> +
> +	ret = ftruncate(-1, 0);
> +	if (ret != -1 || errno != EBADF) {
> +		errno = EINVAL;
> +		return __LINE__;
> +	}
> +
> +	fd = open(filename, O_RDWR | O_CREAT);

Missing the mode argument.
O_TMPFILE would make things easier.

> +	if (fd == -1)
> +		return __LINE__;
> +
> +	ret = ftruncate(fd, -1);
> +	if (ret != -1 || errno != EINVAL) {
> +		if (ret == 0)
> +			errno = EINVAL;
> +		ret = __LINE__;
> +		goto end;
> +	}
> +
> +	ret = ftruncate(fd, 42);
> +	if (ret != 0) {
> +		ret = __LINE__;
> +		goto end;
> +	}
> +
> +	ret = fstat(fd, &stat_buf);
> +	if (ret != 0) {
> +		ret = __LINE__;
> +		goto end;
> +	}
> +
> +	if (stat_buf.st_size != 42) {
> +		errno = EINVAL;
> +		ret = stat_buf.st_size;
> +		goto end;
> +	}

Could you also add a variant which tests that 64-bit values work correctly?

> +
> +end:
> +	close(fd);
> +	unlink(filename);
> +
> +	return ret;
> +}
> +
>  int test_stat_timestamps(void)
>  {
>  	struct stat st;
> @@ -1406,6 +1456,7 @@ int run_syscall(int min, int max)
>  		CASE_TEST(file_stream);       EXPECT_SYSZR(1, test_file_stream()); break;
>  		CASE_TEST(file_stream_wsr);   EXPECT_SYSZR(1, test_file_stream_wsr()); break;
>  		CASE_TEST(fork);              EXPECT_SYSZR(1, test_fork(FORK_STANDARD)); break;
> +		CASE_TEST(ftruncate);         EXPECT_SYSZR(1, test_ftruncate()); break;
>  		CASE_TEST(getdents64_root);   EXPECT_SYSNE(1, test_getdents64("/"), -1); break;
>  		CASE_TEST(getdents64_null);   EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break;
>  		CASE_TEST(directories);       EXPECT_SYSZR(proc, test_dirent()); break;
> -- 
> 2.53.0.473.g4a7958ca14-goog
> 


  reply	other threads:[~2026-03-03  7:09 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-03  1:00 [PATCH v3 0/2] selftests/liveupdate: add end to end test infrastructure and scripts Jordan Richards
2026-03-03  1:00 ` [PATCH v3 1/2] tools/nolibc: add ftruncate() Jordan Richards
2026-03-03  7:09   ` Thomas Weißschuh [this message]
2026-03-03  1:00 ` [PATCH v3 2/2] selftests/liveupdate: add end to end test infrastructure and scripts Jordan Richards

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c65fdf06-2f69-4c81-be21-a14229eaf1b6@t-8ch.de \
    --to=linux@weissschuh.net \
    --cc=dmatlack@google.com \
    --cc=jasonmiu@google.com \
    --cc=jordanrichards@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=rppt@kernel.org \
    --cc=shuah@kernel.org \
    --cc=w@1wt.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox