Messages in this thread Patch in this message |  | | From | Daniel Palmer <> | | Subject | [PATCH v3 2/2] selftests/nolibc: Add a very basic test for fallocate() | | Date | Fri, 1 May 2026 01:41:25 +0900 |
| |
1: Create a tmp file, fallocate() to make it a bit bigger, check the size is what was expected.
2: Try to fallocate() (1 << 20), this should work.
3: Try to fallocate() (1 << 52), this should cause ENOSPC or EFBIG.
2 and 3 are basically to make sure if the offset or size are split into a pair of registers for the syscall that we are passing them the correct way around.
sparc32 seems to return EOPNOTSUPP for fallocate() so skip the test there.
Signed-off-by: Daniel Palmer <daniel@thingy.jp> --- tools/testing/selftests/nolibc/nolibc-test.c | 69 ++++++++++++++++++++ 1 file changed, 69 insertions(+)
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 08610cacf030..a586e9d9ede2 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -89,6 +89,14 @@ static const int is_glibc = #endif ; +static const int is_sparc32 = +#if defined(__sparc__) && !defined(__arch64__) + 1 +#else + 0 +#endif +; + #if !defined(NOLIBC) /* Some disabled tests may not compile. */ @@ -898,6 +906,66 @@ 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; + } + + /* Now try to allocate 1MiB. This puts a single bit + * into one of the registers if the size is split into + * two registers. This shouldn't fail if the bit is in + * the correct register. + */ + r = fallocate(fd, 0, 0, (1ll << 20)); + if (r) + goto close_tmpfile; + + /* Check a massive size that puts a single bit into + * the other register if splitting. + * This should return an error and errno = ENOSPC or + * EFBIG indicating the value was passed correctly but it + * was rejected. + */ + r = fallocate(fd, 0, 0, (1ll << (20 + 32))); + if (r != -1) { + r = -1; + goto close_tmpfile; + } + if (errno != ENOSPC && errno != EFBIG) { + r = -1; + goto close_tmpfile; + } + + /* Test passed */ + r = 0; + +close_tmpfile: + close(fd); + + return r; +} + int test_file_stream(void) { FILE *f; @@ -1507,6 +1575,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(!is_sparc32, 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.53.0
|  |