* [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file @ 2026-09-17 2:56 Gaurav Pathak 2026-09-17 10:53 ` Gaurav Pathak 2026-09-17 11:15 ` [LTP] " linuxtestproject.agent 0 siblings, 2 replies; 11+ messages in thread From: Gaurav Pathak @ 2026-09-17 2:56 UTC (permalink / raw) To: ltp; +Cc: Gaurav Pathak From: Gaurav Pathak <gaurav.pathak@suse.com> This patch adds a new test to validate these atomic write limit fields. The test ensures the filesystem correctly advertises the STATX_ATTR_WRITE_ATOMIC attribute when queried on a file opened with O_DIRECT. It also verifies that the reported optimized maximum is logically consistent by falling within the absolute minimum and maximum boundaries. Furthermore, it checks that all reported atomic write unit sizes are valid powers of two, adhering to the strict requirements of the kernel block layer. If the underlying storage hardware or filesystem lacks atomic write support, the test gracefully skips with TCONF. Fixes: #1224 Signed-off-by: Gaurav Pathak <gaurav.pathak@suse.com> --- configure.ac | 2 +- testcases/kernel/syscalls/statx/.gitignore | 1 + testcases/kernel/syscalls/statx/statx13.c | 130 +++++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 testcases/kernel/syscalls/statx/statx13.c diff --git a/configure.ac b/configure.ac index 18bfdb88c..72f423c56 100644 --- a/configure.ac +++ b/configure.ac @@ -181,7 +181,7 @@ AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) -AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[ +AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align, struct statx.stx_atomic_write_unit_max_opt],,,[ #define _GNU_SOURCE #include <sys/stat.h> ]) diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore index f6a423eed..e601a46a3 100644 --- a/testcases/kernel/syscalls/statx/.gitignore +++ b/testcases/kernel/syscalls/statx/.gitignore @@ -10,3 +10,4 @@ /statx10 /statx11 /statx12 +/statx13 diff --git a/testcases/kernel/syscalls/statx/statx13.c b/testcases/kernel/syscalls/statx/statx13.c new file mode 100644 index 000000000..5f73807b4 --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx13.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 SUSE LLC <gaurav.pathak@suse.com> + */ + +/*\ + * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13). + * It ensures that supported filesystems (xfs as of now) correctly report their + * atomic write limits to user space when queried via statx(). + * + * The test performs the following validations: + * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). + * - Calls statx() with the STATX_WRITE_ATOMIC mask to retrieve the limits. + * - Verifies that stx_atomic_write_unit_min, stx_atomic_write_unit_max, and + * stx_atomic_write_unit_max_opt are logically consistent (e.g., max_opt is + * within the min and max bounds). + * - Ensures all reported atomic write unit sizes are valid powers of two. + */ + +#define _GNU_SOURCE +#include <sys/param.h> +#include "tst_test.h" + +#define MNTPOINT "mnt_point" +#define TESTFILE MNTPOINT"/testfile" +#define MODE 0644 + +#define WRITE_SIZE 4096 +#define ALIGNMENT 4096 + +static int file_fd = -1; + +static void verify_statx(void) +{ + struct statx buff; + + TST_EXP_PASS_SILENT(statx(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff), + "statx(AT_FDCWD, %s, 0, STATX_WRITE_ATOMIC, &buf)", TESTFILE); + + if (!(buff.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) { + tst_res(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); + return; + } + + if (buff.stx_atomic_write_unit_min > 0 && + __builtin_popcount(buff.stx_atomic_write_unit_min) == 1) + tst_res(TPASS, "stx_atomic_write_unit_min(%u) is power of 2", + buff.stx_atomic_write_unit_min); + else + tst_res(TFAIL, "stx_atomic_write_unit_min(%u) is not a power of 2", + buff.stx_atomic_write_unit_min); + + if (buff.stx_atomic_write_unit_max > 0 && + __builtin_popcount(buff.stx_atomic_write_unit_max) == 1) + tst_res(TPASS, "stx_atomic_write_unit_max(%u) is power of 2", + buff.stx_atomic_write_unit_max); + else + tst_res(TFAIL, "stx_atomic_write_unit_max(%u) is not a power of 2", + buff.stx_atomic_write_unit_max); + +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT + if (buff.stx_atomic_write_unit_max_opt == 0) { + tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); + } else { + if (buff.stx_atomic_write_unit_max_opt > buff.stx_atomic_write_unit_max) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", + buff.stx_atomic_write_unit_max_opt, + buff.stx_atomic_write_unit_max); + + else if (buff.stx_atomic_write_unit_max_opt < buff.stx_atomic_write_unit_min) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than min (%u)", + buff.stx_atomic_write_unit_max_opt, + buff.stx_atomic_write_unit_min); + else + tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid range [%u, %u]", + buff.stx_atomic_write_unit_max_opt, + buff.stx_atomic_write_unit_min, + buff.stx_atomic_write_unit_max); + + if (__builtin_popcount(buff.stx_atomic_write_unit_max_opt) != 1) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power of 2", + buff.stx_atomic_write_unit_max_opt); + } +#else + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); +#endif +} + +static void setup(void) +{ + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); + + if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4")) + tst_brk(TCONF, "This test only supports ext4 and xfs"); + + umask(0); + memset(data_buff, '@', WRITE_SIZE); + + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); +} + +static void cleanup(void) +{ + if (file_fd > -1) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .test_all = verify_statx, + .setup = setup, + .cleanup = cleanup, + .min_kver = "6.13", + .needs_root = 1, + .needs_device = 1, + .needs_tmpdir = 1, + .mntpoint = MNTPOINT, + .mount_device = 1, + .filesystems = (struct tst_fs[]) { + { + .type = "xfs", + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL}, + }, + { + .type = "ext4", + .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", "4096", "-C", "65536", NULL}, + }, + {} + }, +}; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 2:56 [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file Gaurav Pathak @ 2026-09-17 10:53 ` Gaurav Pathak 2026-09-17 11:17 ` [LTP] " linuxtestproject.agent ` (3 more replies) 2026-09-17 11:15 ` [LTP] " linuxtestproject.agent 1 sibling, 4 replies; 11+ messages in thread From: Gaurav Pathak @ 2026-09-17 10:53 UTC (permalink / raw) To: ltp; +Cc: Gaurav Pathak From: Gaurav Pathak <gaurav.pathak@suse.com> This patch adds a new test to validate these atomic write limit fields. The test ensures the filesystem correctly advertises the STATX_ATTR_WRITE_ATOMIC attribute when queried on a file opened with O_DIRECT. It also verifies that the reported optimized maximum is logically consistent by falling within the absolute minimum and maximum boundaries. Furthermore, it checks that all reported atomic write unit sizes are valid powers of two, adhering to the strict requirements of the kernel block layer. If the underlying storage hardware or filesystem lacks atomic write support, the test gracefully skips with TCONF. Fixes: #1224 Signed-off-by: Gaurav Pathak <gaurav.pathak@suse.com> --- configure.ac | 2 +- testcases/kernel/syscalls/statx/.gitignore | 1 + testcases/kernel/syscalls/statx/statx13.c | 130 +++++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 testcases/kernel/syscalls/statx/statx13.c diff --git a/configure.ac b/configure.ac index 18bfdb88c..72f423c56 100644 --- a/configure.ac +++ b/configure.ac @@ -181,7 +181,7 @@ AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) -AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[ +AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align, struct statx.stx_atomic_write_unit_max_opt],,,[ #define _GNU_SOURCE #include <sys/stat.h> ]) diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore index f6a423eed..e601a46a3 100644 --- a/testcases/kernel/syscalls/statx/.gitignore +++ b/testcases/kernel/syscalls/statx/.gitignore @@ -10,3 +10,4 @@ /statx10 /statx11 /statx12 +/statx13 diff --git a/testcases/kernel/syscalls/statx/statx13.c b/testcases/kernel/syscalls/statx/statx13.c new file mode 100644 index 000000000..ea42a102c --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx13.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 SUSE LLC <gaurav.pathak@suse.com> + */ + +/*\ + * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13). + * It ensures that supported filesystems (xfs as of now) correctly report their + * atomic write limits to user space when queried via statx(). + * + * The test performs the following validations: + * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). + * - Calls statx() with the STATX_WRITE_ATOMIC mask to retrieve the limits. + * - Verifies that stx_atomic_write_unit_min, stx_atomic_write_unit_max, and + * stx_atomic_write_unit_max_opt are logically consistent (e.g., max_opt is + * within the min and max bounds). + * - Ensures all reported atomic write unit sizes are valid powers of two. + */ + +#define _GNU_SOURCE +#include <sys/param.h> +#include "tst_test.h" + +#define MNTPOINT "mnt_point" +#define TESTFILE MNTPOINT"/testfile" +#define MODE 0644 + +#define WRITE_SIZE 4096 +#define ALIGNMENT 4096 + +static int file_fd = -1; + +static void verify_statx(void) +{ + struct statx buff; + + TST_EXP_PASS_SILENT(statx(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff), + "statx(AT_FDCWD, %s, 0, STATX_WRITE_ATOMIC, &buf)", TESTFILE); + + if (!(buff.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) { + tst_res(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); + return; + } + + if (buff.stx_atomic_write_unit_min > 0 && + __builtin_popcount(buff.stx_atomic_write_unit_min) == 1) + tst_res(TPASS, "stx_atomic_write_unit_min(%u) is power of 2", + buff.stx_atomic_write_unit_min); + else + tst_res(TFAIL, "stx_atomic_write_unit_min(%u) is not a power of 2", + buff.stx_atomic_write_unit_min); + + if (buff.stx_atomic_write_unit_max > 0 && + __builtin_popcount(buff.stx_atomic_write_unit_max) == 1) + tst_res(TPASS, "stx_atomic_write_unit_max(%u) is power of 2", + buff.stx_atomic_write_unit_max); + else + tst_res(TFAIL, "stx_atomic_write_unit_max(%u) is not a power of 2", + buff.stx_atomic_write_unit_max); + +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT + if (buff.stx_atomic_write_unit_max_opt == 0) { + tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); + } else { + if (buff.stx_atomic_write_unit_max_opt > buff.stx_atomic_write_unit_max) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", + buff.stx_atomic_write_unit_max_opt, + buff.stx_atomic_write_unit_max); + + else if (buff.stx_atomic_write_unit_max_opt < buff.stx_atomic_write_unit_min) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than min (%u)", + buff.stx_atomic_write_unit_max_opt, + buff.stx_atomic_write_unit_min); + else + tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid range [%u, %u]", + buff.stx_atomic_write_unit_max_opt, + buff.stx_atomic_write_unit_min, + buff.stx_atomic_write_unit_max); + + if (__builtin_popcount(buff.stx_atomic_write_unit_max_opt) != 1) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power of 2", + buff.stx_atomic_write_unit_max_opt); + } +#else + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); +#endif +} + +static void setup(void) +{ + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); + + if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4")) + tst_brk(TCONF, "This test only supports ext4 and xfs"); + + umask(0); + memset(data_buff, '@', WRITE_SIZE); + + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); +} + +static void cleanup(void) +{ + if (file_fd > -1) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .test_all = verify_statx, + .setup = setup, + .cleanup = cleanup, + .min_kver = "6.13", + .needs_root = 1, + .needs_device = 1, + .needs_tmpdir = 1, + .mntpoint = MNTPOINT, + .mount_device = 1, + .filesystems = (struct tst_fs[]) { + { + .type = "xfs", + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL}, + }, + { + .type = "ext4", + .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", "4096", "-C", "65536", NULL}, + }, + {} + }, +}; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 10:53 ` Gaurav Pathak @ 2026-09-17 11:17 ` linuxtestproject.agent 2026-09-17 14:19 ` [LTP] [PATCH] " Petr Vorel ` (2 subsequent siblings) 3 siblings, 0 replies; 11+ messages in thread From: linuxtestproject.agent @ 2026-09-17 11:17 UTC (permalink / raw) To: Gaurav Pathak; +Cc: ltp Hi Gaurav, On Thu, 17 Sep 2026 16:23:04 +0530, Gaurav Pathak wrote: > syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file > Fixes: #1224 Fixes tags must reference a valid commit SHA in git history. Use Closes: #1224 or a Link tag to reference an issue. > -AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[ > +AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align, struct statx.stx_atomic_write_unit_max_opt],,,[ > #define _GNU_SOURCE > #include <sys/stat.h> > ]) Do not use configure.ac checks to conditionally compile test logic. Instead, add fallback definitions for STATX_WRITE_ATOMIC, STATX_ATTR_WRITE_ATOMIC, and stx_atomic_write_* members in include/lapi/stat.h so the test builds unconditionally. > /*\ > * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13). > * It ensures that supported filesystems (xfs as of now) correctly report their > * atomic write limits to user space when queried via statx(). > * > * The test performs the following validations: > * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). Add a blank line before the bulleted list to comply with reST syntax. > #define _GNU_SOURCE > #include <sys/param.h> > #include "tst_test.h" Include "lapi/stat.h" so statx() and atomic write definitions are available on older C libraries. <sys/param.h> is unused and should be removed. > TST_EXP_PASS_SILENT(statx(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff), > "statx(AT_FDCWD, %s, 0, STATX_WRITE_ATOMIC, &buf)", TESTFILE); > > if (!(buff.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) { TST_EXP_PASS_SILENT() does not abort on error. If statx() fails, execution proceeds to read uninitialized memory from buff. Add "if (!TST_PASS) return;" after the call. Also drop the redundant, mismatched format string. > if (buff.stx_atomic_write_unit_max > 0 && > __builtin_popcount(buff.stx_atomic_write_unit_max) == 1) > tst_res(TPASS, "stx_atomic_write_unit_max(%u) is power of 2", > buff.stx_atomic_write_unit_max); > else > tst_res(TFAIL, "stx_atomic_write_unit_max(%u) is not a power of 2", > buff.stx_atomic_write_unit_max); Assert that buff.stx_atomic_write_unit_min <= buff.stx_atomic_write_unit_max. The ordering between min and max is never checked when stx_atomic_write_unit_max_opt is 0. > #ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT > if (buff.stx_atomic_write_unit_max_opt == 0) { > tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); > } else { > if (buff.stx_atomic_write_unit_max_opt > buff.stx_atomic_write_unit_max) > tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", > buff.stx_atomic_write_unit_max_opt, > buff.stx_atomic_write_unit_max); > > else if (buff.stx_atomic_write_unit_max_opt < buff.stx_atomic_write_unit_min) > tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than min (%u)", > buff.stx_atomic_write_unit_max_opt, > buff.stx_atomic_write_unit_min); > else > tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid range [%u, %u]", > buff.stx_atomic_write_unit_max_opt, > buff.stx_atomic_write_unit_min, > buff.stx_atomic_write_unit_max); > > if (__builtin_popcount(buff.stx_atomic_write_unit_max_opt) != 1) > tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power of 2", > buff.stx_atomic_write_unit_max_opt); > } > #else > tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); > #endif Do not bury #ifdef feature checks inside test functions. Defining the members in include/lapi/stat.h removes the need for this guard and TCONF branch. > static void setup(void) > { > char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); > > if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4")) > tst_brk(TCONF, "This test only supports ext4 and xfs"); > > umask(0); > memset(data_buff, '@', WRITE_SIZE); > > file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); > SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); > } data_buff is allocated with SAFE_MEMALIGN() but never freed. Free data_buff after SAFE_WRITE(), and move the allocation after the filesystem check so it is not leaked on tst_brk(). Also remove the extra space after the '=' assignment. > static void cleanup(void) > { > if (file_fd > -1) > SAFE_CLOSE(file_fd); > } Use if (file_fd != -1) per LTP conventions. Also, add an entry for statx13 to runtest/syscalls. Verdict - Needs revision --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 10:53 ` Gaurav Pathak 2026-09-17 11:17 ` [LTP] " linuxtestproject.agent @ 2026-09-17 14:19 ` Petr Vorel 2026-09-18 11:04 ` gpathak 2026-09-17 14:23 ` Petr Vorel 2026-10-08 14:26 ` [LTP] [PATCH] " Andrea Cervesato via ltp 3 siblings, 1 reply; 11+ messages in thread From: Petr Vorel @ 2026-09-17 14:19 UTC (permalink / raw) To: Gaurav Pathak; +Cc: Gaurav Pathak, ltp Hi Gaurav, nit: this is a second version of the patch, it'd help to distinguish them if you generate it with git format-patch -v2. It's also mentioned (as "-v 2") in our tutorial: https://linux-test-project.readthedocs.io/en/latest/developers/test_case_tutorial.html (Tutorial is slightly outdated both code and instructions but still more or less valid. It should be structured and improved but I still recommend you to read it to get various ideas not covered elsewhere). Also this second patch failed to build in CI. Could you please enable CI in your LTP fork and push the branch before sending? You 1) get results quicker 2) saves our time to look on something which is broken. > This patch adds a new test to validate these atomic write limit fields. > The test ensures the filesystem correctly advertises the STATX_ATTR_WRITE_ATOMIC > attribute when queried on a file opened with O_DIRECT. It also verifies that the > reported optimized maximum is logically consistent by falling within the > absolute minimum and maximum boundaries. Furthermore, it checks that all > reported atomic write unit sizes are valid powers of two, adhering to the strict > requirements of the kernel block layer. > If the underlying storage hardware or filesystem lacks atomic write > support, the test gracefully skips with TCONF. > Fixes: #1224 > Signed-off-by: Gaurav Pathak <gaurav.pathak@suse.com> > --- > configure.ac | 2 +- > testcases/kernel/syscalls/statx/.gitignore | 1 + > testcases/kernel/syscalls/statx/statx13.c | 130 +++++++++++++++++++++ > 3 files changed, 132 insertions(+), 1 deletion(-) Please go over agent reports (it asked for runtest/syscalls already in the first patch). ... > index 000000000..ea42a102c > --- /dev/null > +++ b/testcases/kernel/syscalls/statx/statx13.c > @@ -0,0 +1,130 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2026 SUSE LLC <gaurav.pathak@suse.com> > + */ > + > +/*\ > + * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13). > + * It ensures that supported filesystems (xfs as of now) correctly report their git grep generic_atomic_write_valid (functions mentioned at [1] which was mentioned in the "block atomic writes" feature [2]) mentions also ext4. And you also test both xfs and ext4, you should either update filesystem list in docs or not mention filesystems at all. [1] https://lore.kernel.org/linux-xfs/20240607143919.2622319-1-john.g.garry@oracle.com/T/#t [2] https://lore.kernel.org/lkml/20240620125359.2684798-1-john.g.garry@oracle.com/ > + * atomic write limits to user space when queried via statx(). > + * > + * The test performs the following validations: nit: there needs to be a blank line otherwise list will not be formatted => we should teach agent to recognise it > + * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). > + * - Calls statx() with the STATX_WRITE_ATOMIC mask to retrieve the limits. > + * - Verifies that stx_atomic_write_unit_min, stx_atomic_write_unit_max, and > + * stx_atomic_write_unit_max_opt are logically consistent (e.g., max_opt is And this extra space before stx_atomic_write_unit_max_opt make is formatted as bold (see later doc build) > + * within the min and max bounds). > + * - Ensures all reported atomic write unit sizes are valid powers of two. > + */ > + > +#define _GNU_SOURCE > +#include <sys/param.h> > +#include "tst_test.h" > + > +#define MNTPOINT "mnt_point" > +#define TESTFILE MNTPOINT"/testfile" nit style check complains, you'll find it with: $ make check-statx13 ... CHECK testcases/kernel/syscalls/statx/statx13.c statx13.c:25: CHECK: Concatenated strings should use spaces between elements > +#define MODE 0644 > + > +#define WRITE_SIZE 4096 > +#define ALIGNMENT 4096 > + > +static int file_fd = -1; > + > +static void verify_statx(void) > +{ > + struct statx buff; > + > + TST_EXP_PASS_SILENT(statx(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff), > + "statx(AT_FDCWD, %s, 0, STATX_WRITE_ATOMIC, &buf)", TESTFILE); > + > + if (!(buff.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) { > + tst_res(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); > + return; This is enough (without following return). tst_brk(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); > + } > + > + if (buff.stx_atomic_write_unit_min > 0 && > + __builtin_popcount(buff.stx_atomic_write_unit_min) == 1) > + tst_res(TPASS, "stx_atomic_write_unit_min(%u) is power of 2", > + buff.stx_atomic_write_unit_min); > + else > + tst_res(TFAIL, "stx_atomic_write_unit_min(%u) is not a power of 2", > + buff.stx_atomic_write_unit_min); > + > + if (buff.stx_atomic_write_unit_max > 0 && > + __builtin_popcount(buff.stx_atomic_write_unit_max) == 1) > + tst_res(TPASS, "stx_atomic_write_unit_max(%u) is power of 2", > + buff.stx_atomic_write_unit_max); > + else > + tst_res(TFAIL, "stx_atomic_write_unit_max(%u) is not a power of 2", > + buff.stx_atomic_write_unit_max); > + > +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT > + if (buff.stx_atomic_write_unit_max_opt == 0) { > + tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); Shouldn't this be TPASS? > + } else { > + if (buff.stx_atomic_write_unit_max_opt > buff.stx_atomic_write_unit_max) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_max); > + > + else if (buff.stx_atomic_write_unit_max_opt < buff.stx_atomic_write_unit_min) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than min (%u)", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_min); > + else > + tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid range [%u, %u]", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_min, > + buff.stx_atomic_write_unit_max); > + > + if (__builtin_popcount(buff.stx_atomic_write_unit_max_opt) != 1) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power of 2", > + buff.stx_atomic_write_unit_max_opt); > + } > +#else > + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); > +#endif > +} > + > +static void setup(void) > +{ > + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); > + > + if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4")) > + tst_brk(TCONF, "This test only supports ext4 and xfs"); FYI .filesystems member in struct tst_test test select filesystems, you don't need to check here. Please remove it. => we should teach agent to detect this. > + > + umask(0); > + memset(data_buff, '@', WRITE_SIZE); > + > + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); > + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); > +} > + > +static void cleanup(void) > +{ > + if (file_fd > -1) > + SAFE_CLOSE(file_fd); > +} > + > +static struct tst_test test = { > + .test_all = verify_statx, > + .setup = setup, > + .cleanup = cleanup, > + .min_kver = "6.13", > + .needs_root = 1, > + .needs_device = 1, > + .needs_tmpdir = 1, nit: Some tags aren't needed and will be later deleted. You can see it: $ cd metadata/; make /home/pvorel/install/src/ltp.git/metadata/parse.sh > ltp.json testcases/kernel/syscalls/statx/statx13.c: useless tag: needs_device testcases/kernel/syscalls/statx/statx13.c: useless tag: needs_tmpdir Or you could see it at doc build (but that usually requires python virtualenv and it's slower, OTOH you can check how the doc will look like) $ cd doc; make setup && make => see the docs in thml file: doc/html/users/test_catalog.html#statx13 > + .mntpoint = MNTPOINT, > + .mount_device = 1, > + .filesystems = (struct tst_fs[]) { > + { > + .type = "xfs", > + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL}, > + }, > + { > + .type = "ext4", > + .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", "4096", "-C", "65536", NULL}, BTW my 7.2.0-4.g080d79d-default still TCONF on ext4. Maybe wrong params? > + }, > + {} > + }, > +}; -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 14:19 ` [LTP] [PATCH] " Petr Vorel @ 2026-09-18 11:04 ` gpathak 0 siblings, 0 replies; 11+ messages in thread From: gpathak @ 2026-09-18 11:04 UTC (permalink / raw) To: Petr Vorel; +Cc: Gaurav Pathak, ltp On 2026-09-17 14:19, Petr Vorel wrote: > Hi Gaurav, > > nit: this is a second version of the patch, it'd help to distinguish > them if you > generate it with git format-patch -v2. It's also mentioned (as "-v 2") > in our > tutorial: > > https://linux-test-project.readthedocs.io/en/latest/developers/test_case_tutorial.html > > (Tutorial is slightly outdated both code and instructions but still > more or less > valid. It should be structured and improved but I still recommend you > to read it > to get various ideas not covered elsewhere). > > Also this second patch failed to build in CI. Could you please enable > CI in your > LTP fork and push the branch before sending? You 1) get results quicker > 2) saves > our time to look on something which is broken. > >> This patch adds a new test to validate these atomic write limit >> fields. >> The test ensures the filesystem correctly advertises the >> STATX_ATTR_WRITE_ATOMIC >> attribute when queried on a file opened with O_DIRECT. It also >> verifies that the >> reported optimized maximum is logically consistent by falling within >> the >> absolute minimum and maximum boundaries. Furthermore, it checks that >> all >> reported atomic write unit sizes are valid powers of two, adhering to >> the strict >> requirements of the kernel block layer. > >> If the underlying storage hardware or filesystem lacks atomic write >> support, the test gracefully skips with TCONF. > >> Fixes: #1224 > >> Signed-off-by: Gaurav Pathak <gaurav.pathak@suse.com> >> --- >> configure.ac | 2 +- >> testcases/kernel/syscalls/statx/.gitignore | 1 + >> testcases/kernel/syscalls/statx/statx13.c | 130 >> +++++++++++++++++++++ >> 3 files changed, 132 insertions(+), 1 deletion(-) > > Please go over agent reports (it asked for runtest/syscalls already in > the first patch). > ... >> index 000000000..ea42a102c >> --- /dev/null >> +++ b/testcases/kernel/syscalls/statx/statx13.c >> @@ -0,0 +1,130 @@ >> +// SPDX-License-Identifier: GPL-2.0-or-later >> +/* >> + * Copyright (c) 2026 SUSE LLC <gaurav.pathak@suse.com> >> + */ >> + >> +/*\ >> + * This test validates the STATX_WRITE_ATOMIC feature (introduced in >> Linux 6.13). >> + * It ensures that supported filesystems (xfs as of now) correctly >> report their > git grep generic_atomic_write_valid (functions mentioned at [1] which > was > mentioned in the "block atomic writes" feature [2]) mentions also ext4. > And you > also test both xfs and ext4, you should either update filesystem list > in docs or > not mention filesystems at all. > > [1] > https://lore.kernel.org/linux-xfs/20240607143919.2622319-1-john.g.garry@oracle.com/T/#t > [2] > https://lore.kernel.org/lkml/20240620125359.2684798-1-john.g.garry@oracle.com/ > >> + * atomic write limits to user space when queried via statx(). >> + * >> + * The test performs the following validations: > nit: there needs to be a blank line otherwise list will not be > formatted > > => we should teach agent to recognise it > >> + * - Creates a test file using O_DIRECT (a prerequisite for atomic >> writes). >> + * - Calls statx() with the STATX_WRITE_ATOMIC mask to retrieve the >> limits. >> + * - Verifies that stx_atomic_write_unit_min, >> stx_atomic_write_unit_max, and >> + * stx_atomic_write_unit_max_opt are logically consistent (e.g., >> max_opt is > And this extra space before stx_atomic_write_unit_max_opt make is > formatted as > bold (see later doc build) > >> + * within the min and max bounds). >> + * - Ensures all reported atomic write unit sizes are valid powers of >> two. >> + */ >> + >> +#define _GNU_SOURCE >> +#include <sys/param.h> >> +#include "tst_test.h" >> + >> +#define MNTPOINT "mnt_point" >> +#define TESTFILE MNTPOINT"/testfile" > > nit style check complains, you'll find it with: > $ make check-statx13 > ... > CHECK testcases/kernel/syscalls/statx/statx13.c > statx13.c:25: CHECK: Concatenated strings should use spaces between > elements > > >> +#define MODE 0644 >> + >> +#define WRITE_SIZE 4096 >> +#define ALIGNMENT 4096 >> + >> +static int file_fd = -1; >> + >> +static void verify_statx(void) >> +{ >> + struct statx buff; >> + >> + TST_EXP_PASS_SILENT(statx(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | >> STATX_WRITE_ATOMIC, &buff), >> + "statx(AT_FDCWD, %s, 0, STATX_WRITE_ATOMIC, &buf)", TESTFILE); >> + >> + if (!(buff.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) { >> + tst_res(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); >> + return; > > This is enough (without following return). > tst_brk(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); >> + } >> + >> + if (buff.stx_atomic_write_unit_min > 0 && >> + __builtin_popcount(buff.stx_atomic_write_unit_min) == 1) >> + tst_res(TPASS, "stx_atomic_write_unit_min(%u) is power of 2", >> + buff.stx_atomic_write_unit_min); >> + else >> + tst_res(TFAIL, "stx_atomic_write_unit_min(%u) is not a power of 2", >> + buff.stx_atomic_write_unit_min); >> + >> + if (buff.stx_atomic_write_unit_max > 0 && >> + __builtin_popcount(buff.stx_atomic_write_unit_max) == 1) >> + tst_res(TPASS, "stx_atomic_write_unit_max(%u) is power of 2", >> + buff.stx_atomic_write_unit_max); >> + else >> + tst_res(TFAIL, "stx_atomic_write_unit_max(%u) is not a power of 2", >> + buff.stx_atomic_write_unit_max); >> + >> +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT >> + if (buff.stx_atomic_write_unit_max_opt == 0) { >> + tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized >> max reported)"); > Shouldn't this be TPASS? > >> + } else { >> + if (buff.stx_atomic_write_unit_max_opt > >> buff.stx_atomic_write_unit_max) >> + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max >> (%u)", >> + buff.stx_atomic_write_unit_max_opt, >> + buff.stx_atomic_write_unit_max); >> + >> + else if (buff.stx_atomic_write_unit_max_opt < >> buff.stx_atomic_write_unit_min) >> + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than >> min (%u)", >> + buff.stx_atomic_write_unit_max_opt, >> + buff.stx_atomic_write_unit_min); >> + else >> + tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid >> range [%u, %u]", >> + buff.stx_atomic_write_unit_max_opt, >> + buff.stx_atomic_write_unit_min, >> + buff.stx_atomic_write_unit_max); >> + >> + if (__builtin_popcount(buff.stx_atomic_write_unit_max_opt) != 1) >> + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power >> of 2", >> + buff.stx_atomic_write_unit_max_opt); >> + } >> +#else >> + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in >> struct statx"); >> +#endif >> +} >> + >> +static void setup(void) >> +{ >> + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); >> + >> + if (strcmp(tst_device->fs_type, "xfs") && >> strcmp(tst_device->fs_type, "ext4")) >> + tst_brk(TCONF, "This test only supports ext4 and xfs"); > FYI .filesystems member in struct tst_test test select filesystems, you > don't > need to check here. Please remove it. > > => we should teach agent to detect this. > >> + >> + umask(0); >> + memset(data_buff, '@', WRITE_SIZE); >> + >> + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); >> + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); >> +} >> + >> +static void cleanup(void) >> +{ >> + if (file_fd > -1) >> + SAFE_CLOSE(file_fd); >> +} >> + >> +static struct tst_test test = { >> + .test_all = verify_statx, >> + .setup = setup, >> + .cleanup = cleanup, >> + .min_kver = "6.13", >> + .needs_root = 1, >> + .needs_device = 1, >> + .needs_tmpdir = 1, > nit: Some tags aren't needed and will be later deleted. You can see it: > > $ cd metadata/; make > /home/pvorel/install/src/ltp.git/metadata/parse.sh > ltp.json > testcases/kernel/syscalls/statx/statx13.c: useless tag: needs_device > testcases/kernel/syscalls/statx/statx13.c: useless tag: needs_tmpdir > > Or you could see it at doc build (but that usually requires python > virtualenv > and it's slower, OTOH you can check how the doc will look like) > > $ cd doc; make setup && make > => see the docs in thml file: > doc/html/users/test_catalog.html#statx13 > >> + .mntpoint = MNTPOINT, >> + .mount_device = 1, >> + .filesystems = (struct tst_fs[]) { >> + { >> + .type = "xfs", >> + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL}, >> + }, >> + { >> + .type = "ext4", >> + .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", >> "4096", "-C", "65536", NULL}, > BTW my 7.2.0-4.g080d79d-default still TCONF on ext4. Maybe wrong > params? >> + }, >> + {} >> + }, >> +}; Hello Petr, Thanks a lot for reviewing the patch and providing useful pointers. I am able to fix almost all of the issues reviewed by you and reported by automation agent. >>> + .type = "ext4", >>> + .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", >>> "4096", "-C", "65536", NULL}, >> BTW my 7.2.0-4.g080d79d-default still TCONF on ext4. Maybe wrong >> params? However, for ext4 filesystem case, I used scsi_debug kernel module to emulate the behavior of allowing 16K write operation using O_DIRECT flag which is bigger than the PAGESIZE of 4096. On my system and some other machines on which I ran this test, ext4 is not allowing me to cross PAGESIZE boundary, maybe because the kernel running on those machines is compiled with 4K PAGESIZE. I believe this is also the same in your case. Maybe we need to test this on a kernel having PAGESIZE greater than 4096. -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 10:53 ` Gaurav Pathak 2026-09-17 11:17 ` [LTP] " linuxtestproject.agent 2026-09-17 14:19 ` [LTP] [PATCH] " Petr Vorel @ 2026-09-17 14:23 ` Petr Vorel 2026-09-18 11:12 ` [LTP] [PATCH v3] " Gaurav Pathak 2026-10-08 14:26 ` [LTP] [PATCH] " Andrea Cervesato via ltp 3 siblings, 1 reply; 11+ messages in thread From: Petr Vorel @ 2026-09-17 14:23 UTC (permalink / raw) To: Gaurav Pathak; +Cc: Gaurav Pathak, ltp Hi all, > This patch adds a new test to validate these atomic write limit fields. > The test ensures the filesystem correctly advertises the STATX_ATTR_WRITE_ATOMIC > attribute when queried on a file opened with O_DIRECT. It also verifies that the > reported optimized maximum is logically consistent by falling within the > absolute minimum and maximum boundaries. Furthermore, it checks that all > reported atomic write unit sizes are valid powers of two, adhering to the strict > requirements of the kernel block layer. > If the underlying storage hardware or filesystem lacks atomic write > support, the test gracefully skips with TCONF. > Fixes: #1224 ... > diff --git a/testcases/kernel/syscalls/statx/statx13.c b/testcases/kernel/syscalls/statx/statx13.c > new file mode 100644 > index 000000000..ea42a102c > --- /dev/null > +++ b/testcases/kernel/syscalls/statx/statx13.c ... > +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT Looking at this, I wonder why this and also older statx10.c, statx11.c does not use ltp_statx added by Andrea in d89a232a7b ("Add SAFE_STATX macro") Kind regards, Petr > + if (buff.stx_atomic_write_unit_max_opt == 0) { > + tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); > + } else { > + if (buff.stx_atomic_write_unit_max_opt > buff.stx_atomic_write_unit_max) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_max); > + > + else if (buff.stx_atomic_write_unit_max_opt < buff.stx_atomic_write_unit_min) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than min (%u)", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_min); > + else > + tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid range [%u, %u]", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_min, > + buff.stx_atomic_write_unit_max); > + > + if (__builtin_popcount(buff.stx_atomic_write_unit_max_opt) != 1) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power of 2", > + buff.stx_atomic_write_unit_max_opt); > + } > +#else > + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); > +#endif > +} -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* [LTP] [PATCH v3] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 14:23 ` Petr Vorel @ 2026-09-18 11:12 ` Gaurav Pathak 2026-09-18 12:51 ` [LTP] " linuxtestproject.agent 0 siblings, 1 reply; 11+ messages in thread From: Gaurav Pathak @ 2026-09-18 11:12 UTC (permalink / raw) To: ltp; +Cc: Gaurav Pathak From: Gaurav Pathak <gaurav.pathak@suse.com> This patch adds a new test to validate these atomic write limit fields. The test ensures the filesystem correctly advertises the STATX_ATTR_WRITE_ATOMIC attribute when queried on a file opened with O_DIRECT. It also verifies that the reported optimized maximum is logically consistent by falling within the absolute minimum and maximum boundaries. Furthermore, it checks that all reported atomic write unit sizes are valid powers of two, adhering to the strict requirements of the kernel block layer. If the underlying storage hardware or filesystem lacks atomic write support, the test gracefully skips with TCONF. Closes: #1224 Signed-off-by: Gaurav Pathak <gaurav.pathak@suse.com> --- configure.ac | 4 +- include/lapi/stat.h | 17 ++- runtest/syscalls | 1 + testcases/kernel/syscalls/statx/.gitignore | 1 + testcases/kernel/syscalls/statx/statx13.c | 139 +++++++++++++++++++++ 5 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 testcases/kernel/syscalls/statx/statx13.c diff --git a/configure.ac b/configure.ac index 18bfdb88c..d5a609fa7 100644 --- a/configure.ac +++ b/configure.ac @@ -181,7 +181,9 @@ AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) -AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[ +AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align, struct statx.stx_atomic_write_unit_max_opt, + struct statx.stx_atomic_write_unit_min, struct statx.stx_atomic_write_unit_max, + struct statx.stx_atomic_write_segments_max],,,[ #define _GNU_SOURCE #include <sys/stat.h> ]) diff --git a/include/lapi/stat.h b/include/lapi/stat.h index 17b62ea98..859e410ab 100644 --- a/include/lapi/stat.h +++ b/include/lapi/stat.h @@ -93,7 +93,14 @@ struct statx_timestamp { uint64_t stx_mnt_id; \ uint32_t stx_dio_mem_align; \ uint32_t stx_dio_offset_align; \ - uint64_t __spare3[12]; \ + uint64_t stx_subvol; \ + uint32_t stx_atomic_write_unit_min; \ + uint32_t stx_atomic_write_unit_max; \ + uint32_t stx_atomic_write_segments_max; \ + uint32_t stx_dio_read_offset_align; \ + uint32_t stx_atomic_write_unit_max_opt; \ + uint32_t __spare2[1]; \ + uint64_t __spare3[8]; \ }; LTP_DEFINE_STATX_STRUCT(statx_fallback); @@ -197,6 +204,10 @@ static inline int statx(int dirfd, const char *pathname, unsigned int flags, # define STATX_DIOALIGN 0x00002000U #endif +#ifndef STATX_WRITE_ATOMIC +#define STATX_WRITE_ATOMIC 0x00010000U +#endif + #ifndef STATX__RESERVED # define STATX__RESERVED 0x80000000U #endif @@ -248,6 +259,10 @@ static inline int statx(int dirfd, const char *pathname, unsigned int flags, # define STATX_MNT_ID_UNIQUE 0x00004000U #endif +#ifndef STATX_ATTR_WRITE_ATOMIC +#define STATX_ATTR_WRITE_ATOMIC 0x00400000 +#endif + #define SAFE_FCHMODAT2(dfd, filename, mode, flags) \ safe_fchmodat2(__FILE__, __LINE__, (dfd), (filename), (mode), (flags)) diff --git a/runtest/syscalls b/runtest/syscalls index d953f0558..b8c7fbb0f 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -1926,6 +1926,7 @@ statx09 statx09 statx10 statx10 statx11 statx11 statx12 statx12 +statx13 statx13 membarrier01 membarrier01 diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore index f6a423eed..e601a46a3 100644 --- a/testcases/kernel/syscalls/statx/.gitignore +++ b/testcases/kernel/syscalls/statx/.gitignore @@ -10,3 +10,4 @@ /statx10 /statx11 /statx12 +/statx13 diff --git a/testcases/kernel/syscalls/statx/statx13.c b/testcases/kernel/syscalls/statx/statx13.c new file mode 100644 index 000000000..cc445fa57 --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx13.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 SUSE LLC <gaurav.pathak@suse.com> + */ + +/*\ + * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13). + * It ensures that supported filesystems (xfs and nfs) correctly report their + * atomic write limits to user space when queried via statx(). + * + * The test performs the following validations: + * + * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). + * - Calls statx() with the STATX_WRITE_ATOMIC mask to retrieve the limits. + * - Verifies that stx_atomic_write_unit_min, stx_atomic_write_unit_max, and + * stx_atomic_write_unit_max_opt are logically consistent (e.g., max_opt is + * within the min and max bounds). + * - Ensures all reported atomic write unit sizes are valid powers of two. + */ + +#define _GNU_SOURCE +#include "tst_test.h" +#include "lapi/stat.h" + +#define MNTPOINT "mnt_point" +#define TESTFILE MNTPOINT "/testfile" +#define MODE 0644 + +#define WRITE_SIZE 4096 +#define ALIGNMENT 4096 + +static int file_fd = -1; + +static void verify_statx(void) +{ + struct ltp_statx buff; + + TST_EXP_PASS_SILENT(SAFE_STATX(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff)); + + if (!TST_PASS) + return; + + if (!(buff.data.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) + tst_brk(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC"); + +#if HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN + if (buff.data.stx_atomic_write_unit_min <= buff.data.stx_atomic_write_unit_max) + tst_res(TPASS, "stx_atomic_write_unit_min(%u) <= stx_atomic_write_unit_max(%u)", + buff.data.stx_atomic_write_unit_min, buff.data.stx_atomic_write_unit_max); + else + tst_res(TFAIL, "stx_atomic_write_unit_min(%u) > stx_atomic_write_unit_max(%u)", + buff.data.stx_atomic_write_unit_min, buff.data.stx_atomic_write_unit_max); + + if (buff.data.stx_atomic_write_unit_min > 0 && + __builtin_popcount(buff.data.stx_atomic_write_unit_min) == 1) + tst_res(TPASS, "stx_atomic_write_unit_min(%u) is power of 2", + buff.data.stx_atomic_write_unit_min); + else + tst_res(TFAIL, "stx_atomic_write_unit_min(%u) is not a power of 2", + buff.data.stx_atomic_write_unit_min); + + if (buff.data.stx_atomic_write_unit_max > 0 && + __builtin_popcount(buff.data.stx_atomic_write_unit_max) == 1) + tst_res(TPASS, "stx_atomic_write_unit_max(%u) is power of 2", + buff.data.stx_atomic_write_unit_max); + else + tst_res(TFAIL, "stx_atomic_write_unit_max(%u) is not a power of 2", + buff.data.stx_atomic_write_unit_max); +#else + tst_res(TCONF, "stx_atomic_write_unit_max or stx_atomic_write_unit_min is not defined in struct statx"); +#endif + +#if HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT + if (buff.data.stx_atomic_write_unit_max_opt == 0) { + tst_res(TPASS, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); + } else { + if (buff.data.stx_atomic_write_unit_max_opt > buff.data.stx_atomic_write_unit_max) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", + buff.data.stx_atomic_write_unit_max_opt, + buff.data.stx_atomic_write_unit_max); + + else if (buff.data.stx_atomic_write_unit_max_opt < buff.data.stx_atomic_write_unit_min) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is less than min (%u)", + buff.data.stx_atomic_write_unit_max_opt, + buff.data.stx_atomic_write_unit_min); + else + tst_res(TPASS, "stx_atomic_write_unit_max_opt (%u) is within valid range [%u, %u]", + buff.data.stx_atomic_write_unit_max_opt, + buff.data.stx_atomic_write_unit_min, + buff.data.stx_atomic_write_unit_max); + + if (__builtin_popcount(buff.data.stx_atomic_write_unit_max_opt) != 1) + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) is not a power of 2", + buff.data.stx_atomic_write_unit_max_opt); + } +#else + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); +#endif +} + +static void setup(void) +{ + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); + + umask(0); + memset(data_buff, '@', WRITE_SIZE); + + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); + + free(data_buff); +} + +static void cleanup(void) +{ + if (file_fd != -1) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .test_all = verify_statx, + .setup = setup, + .cleanup = cleanup, + .min_kver = "6.11", + .needs_root = 1, + .mntpoint = MNTPOINT, + .mount_device = 1, + .filesystems = (struct tst_fs[]) { + { + .type = "xfs", + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL}, + }, + { + .type = "ext4", + .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", "4096", "-C", "65536", NULL}, + }, + {} + }, +}; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-18 11:12 ` [LTP] [PATCH v3] " Gaurav Pathak @ 2026-09-18 12:51 ` linuxtestproject.agent 2026-10-05 13:18 ` Andrea Cervesato via ltp 0 siblings, 1 reply; 11+ messages in thread From: linuxtestproject.agent @ 2026-09-18 12:51 UTC (permalink / raw) To: Gaurav Pathak; +Cc: ltp Hi Gaurav, On Thu Sep 17 16:23:04 2026 +0530, Gaurav Pathak wrote: > syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file > Fixes: #1224 > > Signed-off-by: Gaurav Pathak <gaurav.pathak@suse.com> > Closes: #1224 or a Link tag to reference an issue. Fixes: tags must reference a commit SHA present in git history, not an issue. Use Closes: #1224 to reference the issue. Also remove the unedited template instruction "or a Link tag to reference an issue." from the Closes tag. > diff --git a/configure.ac b/configure.ac > index 18bfdb88c..72f423c56 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -181,7 +181,7 @@ AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) > AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) > AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) > AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) > -AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[ > +AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align, struct statx.stx_atomic_write_unit_max_opt],,,[ > #define _GNU_SOURCE > #include <sys/stat.h> > ]) configure.ac checks may only enable fallback API definitions in include/lapi/. Fallback definitions for struct statx extensions and atomic write flags should be added to include/lapi/stat.h instead. > diff --git a/testcases/kernel/syscalls/statx/statx13.c b/testcases/kernel/syscalls/statx/statx13.c > new file mode 100644 > index 000000000..ea42a102c > --- /dev/null > +++ b/testcases/kernel/syscalls/statx/statx13.c Add an entry for statx13 to runtest/syscalls. > +/*\ > + * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13). > + * It ensures that supported filesystems (xfs as of now) correctly report their > + * atomic write limits to user space when queried via statx(). > + * > + * The test performs the following validations: > + * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). Insert a blank line before the bulleted list so Sphinx can parse the reST block correctly. Also, reference the syscall as :manpage:`statx(2)`. > +#define TESTFILE MNTPOINT"/testfile" Add a space between concatenated string literals: MNTPOINT "/testfile". > +#define _GNU_SOURCE > +#include <sys/param.h> > +#include "tst_test.h" Include "lapi/stat.h". Fallback definitions for STATX_WRITE_ATOMIC, STATX_ATTR_WRITE_ATOMIC, and atomic write fields in struct statx must be provided in include/lapi/stat.h so the test compiles on older C libraries. > +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT > + if (buff.stx_atomic_write_unit_max_opt == 0) { Do not place #ifdef guards inside function bodies. Define the fallback struct in include/lapi/stat.h so the test code compiles unconditionally. > + if (buff.stx_atomic_write_unit_max_opt > buff.stx_atomic_write_unit_max) > + tst_res(TFAIL, "stx_atomic_write_unit_max_opt (%u) exceeds max (%u)", > + buff.stx_atomic_write_unit_max_opt, > + buff.stx_atomic_write_unit_max); > + > + else if (buff.stx_atomic_write_unit_max_opt < buff.stx_atomic_write_unit_min) Remove the blank line between if and else if to follow kernel coding style. > +static void setup(void) > +{ > + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); > + > + if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4")) > + tst_brk(TCONF, "This test only supports ext4 and xfs"); > + > + umask(0); > + memset(data_buff, '@', WRITE_SIZE); > + > + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); > + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); > +} data_buff is never freed, leaking memory. Move the allocation after the filesystem check and call free(data_buff) after SAFE_WRITE(). Also remove the double space after '=' in file_fd assignment. > +static void cleanup(void) > +{ > + if (file_fd > -1) > + SAFE_CLOSE(file_fd); > +} Use if (file_fd != -1) instead of file_fd > -1 to match the LTP convention. Verdict - Needs revision --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-18 12:51 ` [LTP] " linuxtestproject.agent @ 2026-10-05 13:18 ` Andrea Cervesato via ltp 0 siblings, 0 replies; 11+ messages in thread From: Andrea Cervesato via ltp @ 2026-10-05 13:18 UTC (permalink / raw) To: linuxtestproject.agent; +Cc: ltp, Gaurav Pathak All AI spotted errors are correct. Please update the patch. Regards, -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 10:53 ` Gaurav Pathak ` (2 preceding siblings ...) 2026-09-17 14:23 ` Petr Vorel @ 2026-10-08 14:26 ` Andrea Cervesato via ltp 3 siblings, 0 replies; 11+ messages in thread From: Andrea Cervesato via ltp @ 2026-10-08 14:26 UTC (permalink / raw) To: Gaurav Pathak; +Cc: Gaurav Pathak, ltp Hi Gaurav, please make sure you are using the versioning tag. Probably to start using b4 is the right approach: I use it for more than a year now and it's easier to track versions in that way. Without using a proper tag, both patchwork and ltp-agent are tracking patches in the wrong way, causing (like in this case) a wrong review from the agent. Regards, -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file 2026-09-17 2:56 [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file Gaurav Pathak 2026-09-17 10:53 ` Gaurav Pathak @ 2026-09-17 11:15 ` linuxtestproject.agent 1 sibling, 0 replies; 11+ messages in thread From: linuxtestproject.agent @ 2026-09-17 11:15 UTC (permalink / raw) To: Gaurav Pathak; +Cc: ltp Hi Gaurav, On Thu Sep 17 16:23:04 2026 +0530, Gaurav Pathak <gaurav.pathak@suse.com> wrote: > syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file > Fixes: #1224 Fixes: must reference a valid commit SHA in local git history. If referencing a GitHub issue, use Closes: #1224 instead. > diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore > index f6a423eed..e601a46a3 100644 > --- a/testcases/kernel/syscalls/statx/.gitignore > +++ b/testcases/kernel/syscalls/statx/.gitignore > @@ -10,3 +10,4 @@ > /statx10 > /statx11 > /statx12 > +/statx13 The new test must also be added to runtest/syscalls. > -AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align],,,[ > +AC_CHECK_MEMBERS([struct statx.stx_mnt_id, struct statx.stx_dio_mem_align, struct statx.stx_atomic_write_unit_max_opt],,,[ > #define _GNU_SOURCE > #include <sys/stat.h> > ]) Compile-time checks in configure.ac may only enable fallback API definitions in include/lapi/. Fallback definitions for STATX_WRITE_ATOMIC, STATX_ATTR_WRITE_ATOMIC, and the atomic write struct statx fields belong in include/lapi/stat.h so the test builds on distributions with older libc headers. > + * The test performs the following validations: > + * - Creates a test file using O_DIRECT (a prerequisite for atomic writes). > + * - Calls statx() with the STATX_WRITE_ATOMIC mask to retrieve the limits. > + * - Verifies that stx_atomic_write_unit_min, stx_atomic_write_unit_max, and > + * stx_atomic_write_unit_max_opt are logically consistent (e.g., max_opt is > + * within the min and max bounds). > + * - Ensures all reported atomic write unit sizes are valid powers of two. Add a blank line before the bulleted list. Reference the syscall as :manpage:`statx(2)` and align the continuation indentation on line 15. Also update the doc comment regarding supported filesystems since ext4 is tested as well. > +#define _GNU_SOURCE > +#include <sys/param.h> > +#include "tst_test.h" > + > +#define MNTPOINT "mnt_point" > +#define TESTFILE MNTPOINT"/testfile" Drop unused <sys/param.h> and include "lapi/stat.h". Add a space between concatenated string literals: MNTPOINT "/testfile". > +static void verify_statx(void) > +{ > + struct statx buff; Tested syscall struct arguments must not be allocated on the stack. Declare a static pointer and allocate it via .bufs in struct tst_test. > +#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT > + if (buff.stx_atomic_write_unit_max_opt == 0) { > + tst_res(TINFO, "stx_atomic_write_unit_max_opt is 0 (no optimized max reported)"); > + } else { [...] > +#else > + tst_res(TCONF, "stx_atomic_write_unit_max_opt is not defined in struct statx"); > +#endif Compile-time feature guards must not be placed inside function bodies. Provide fallback definitions in include/lapi/stat.h instead. > +static void setup(void) > +{ > + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE); > + > + if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4")) > + tst_brk(TCONF, "This test only supports ext4 and xfs"); > + > + umask(0); > + memset(data_buff, '@', WRITE_SIZE); > + > + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE); > + SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, WRITE_SIZE); > +} data_buff is never freed, leaking memory. Free it after SAFE_WRITE(), and perform the allocation after the filesystem check to avoid leaking on tst_brk(). > +static void cleanup(void) > +{ > + if (file_fd > -1) > + SAFE_CLOSE(file_fd); > +} Use if (file_fd != -1) to check file descriptor validity. Also, file_fd is kept open across test iterations but verify_statx() only accesses TESTFILE by path; close file_fd in setup() after writing if fd-based statx is not tested. Verdict - Needs revision --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-10-08 14:27 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-17 2:56 [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file Gaurav Pathak 2026-09-17 10:53 ` Gaurav Pathak 2026-09-17 11:17 ` [LTP] " linuxtestproject.agent 2026-09-17 14:19 ` [LTP] [PATCH] " Petr Vorel 2026-09-18 11:04 ` gpathak 2026-09-17 14:23 ` Petr Vorel 2026-09-18 11:12 ` [LTP] [PATCH v3] " Gaurav Pathak 2026-09-18 12:51 ` [LTP] " linuxtestproject.agent 2026-10-05 13:18 ` Andrea Cervesato via ltp 2026-10-08 14:26 ` [LTP] [PATCH] " Andrea Cervesato via ltp 2026-09-17 11:15 ` [LTP] " linuxtestproject.agent
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox