* [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; 16+ 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] 16+ 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; 16+ 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] 16+ 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
2026-10-12 7:23 ` [LTP] [PATCH v4 0/1] " Gaurav Pathak
1 sibling, 1 reply; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ 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; 16+ 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] 16+ messages in thread
* [LTP] [PATCH v4 0/1] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-09-17 11:15 ` [LTP] " linuxtestproject.agent
@ 2026-10-12 7:23 ` Gaurav Pathak
2026-10-12 7:23 ` [LTP] [PATCH v4 1/1] " Gaurav Pathak
0 siblings, 1 reply; 16+ messages in thread
From: Gaurav Pathak @ 2026-10-12 7:23 UTC (permalink / raw)
To: ltp; +Cc: Gaurav Pathak
From: Gaurav Pathak <gaurav.pathak@suse.com>
Hi,
Thank you for the detailed feedback. I have addressed all the issues pointed out
by the LTP AI Reviewer—including fixing the memory leak, correcting the statx
struct allocation, moving the feature guards to lapi/stat.h, and fixing the
commit reference format.
Please find the revised v4 patch.
Gaurav Pathak (1):
syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular
file
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
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 16+ messages in thread
* [LTP] [PATCH v4 1/1] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-12 7:23 ` [LTP] [PATCH v4 0/1] " Gaurav Pathak
@ 2026-10-12 7:23 ` Gaurav Pathak
2026-10-12 12:43 ` Andrea Cervesato via ltp
0 siblings, 1 reply; 16+ messages in thread
From: Gaurav Pathak @ 2026-10-12 7:23 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] 16+ messages in thread
* Re: [LTP] [PATCH v4 1/1] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-12 7:23 ` [LTP] [PATCH v4 1/1] " Gaurav Pathak
@ 2026-10-12 12:43 ` Andrea Cervesato via ltp
2026-10-13 9:07 ` [LTP] [PATCH v5] " Gaurav Pathak
0 siblings, 1 reply; 16+ messages in thread
From: Andrea Cervesato via ltp @ 2026-10-12 12:43 UTC (permalink / raw)
To: Gaurav Pathak; +Cc: Gaurav Pathak, ltp
Hi Gaurav,
> 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
we don't add Github tags in the git history, please remove it.
>
> 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.
This looks more like [Algorithm] section.
> + */
> +
> +#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
We need to use the right page size when we use O_DIRECT. Please take a look
at the other tests using O_DIRECT, so we avoid defining a default value for it.
> +
> +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));
SAFE_STATX() will fail the syscall, so it shadows TST_EXP_PASS_SILENT().
We need to use raw statx() in these cases, because it's our subject of test,
performing a TST_EXP_PASS() check on it.
We really want to know if statx() fails when STATX_WRITE_ATOMIC is passed.
> +
> + 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
This is not correct. If stx_atomic_write_unit_max is not defined, we should
fallback that into the LTP fallback headers and _before_ even starting the
test, check if statx() supports it. If it doesn't then we can TCONF.
> +
> +#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
Same mistake here.
> +}
> +
> +static void setup(void)
> +{
> + char *data_buff = SAFE_MEMALIGN(ALIGNMENT, WRITE_SIZE);
> +
> + umask(0);
This is not needed.
> + 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);
SAFE_CLOSE() goes here.
> +
> + free(data_buff);
> +}
> +
> +static void cleanup(void)
> +{
> + if (file_fd != -1)
> + SAFE_CLOSE(file_fd);
We can close it right after SAFE_WRITE() because file descriptior is never
in use during the test.
> +}
> +
> +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
--
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] 16+ messages in thread
* [LTP] [PATCH v5] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-12 12:43 ` Andrea Cervesato via ltp
@ 2026-10-13 9:07 ` Gaurav Pathak
2026-10-13 11:27 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 16+ messages in thread
From: Gaurav Pathak @ 2026-10-13 9:07 UTC (permalink / raw)
To: ltp; +Cc: Gaurav Pathak
From: Gaurav Pathak <gaurav.pathak@suse.com>
This patch adds a new test to validate the 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.
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 | 125 +++++++++++++++++++++
5 files changed, 146 insertions(+), 2 deletions(-)
create mode 100644 testcases/kernel/syscalls/statx/statx13.c
diff --git a/configure.ac b/configure.ac
index 370c2e74f..8ec6720dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,7 +180,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 accdf2df9..c0d8eb31e 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1947,6 +1947,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..01a22a458
--- /dev/null
+++ b/testcases/kernel/syscalls/statx/statx13.c
@@ -0,0 +1,125 @@
+// 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().
+ *
+ * Minimum Linux version required is v6.11.
+ */
+
+#define _GNU_SOURCE
+#include "tst_test.h"
+#include "lapi/stat.h"
+
+#define MNTPOINT "mnt_point"
+#define TESTFILE MNTPOINT "/testfile"
+#define MODE 0644
+
+static int file_fd = -1;
+
+static void verify_statx(void)
+{
+ struct ltp_statx buff;
+
+ TST_EXP_PASS(statx(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff.buff),
+ "statx(AT_FDCWD, %s, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buf)", TESTFILE);
+
+ /* Check if the kernel populated the atomic limit struct members */
+ if (!(buff.data.stx_mask & STATX_WRITE_ATOMIC))
+ tst_brk(TCONF, "Kernel may be too old to report atomic limits: STATX_WRITE_ATOMIC missing from stx_mask");
+
+ /* Check if the filesystem supports reporting the atomic write attribute */
+ if (!(buff.data.stx_attributes_mask & STATX_ATTR_WRITE_ATOMIC))
+ tst_brk(TCONF, "FS atomic query unsupported: STATX_ATTR_WRITE_ATOMIC missing from stx_attributes_mask.");
+
+ /* Check if the file/device actively supports atomic writes */
+ if (!(buff.data.stx_attributes & STATX_ATTR_WRITE_ATOMIC))
+ tst_brk(TCONF, "STATX_WRITE_ATOMIC unsupported by block dev or filesystem: STATX_ATTR_WRITE_ATOMIC missing from stx_attributes");
+
+ 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);
+
+ 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);
+ }
+}
+
+static void setup(void)
+{
+ char *data_buff = NULL;
+ struct stat sb;
+
+ SAFE_STAT(MNTPOINT, &sb);
+
+ data_buff = SAFE_MEMALIGN(sb.st_blksize, sb.st_blksize);
+ memset(data_buff, '@', sb.st_blksize);
+
+ file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT | O_DIRECT, MODE);
+ SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, sb.st_blksize);
+
+ SAFE_CLOSE(file_fd);
+ free(data_buff);
+}
+
+static struct tst_test test = {
+ .test_all = verify_statx,
+ .setup = setup,
+ .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] 16+ messages in thread
* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-13 9:07 ` [LTP] [PATCH v5] " Gaurav Pathak
@ 2026-10-13 11:27 ` linuxtestproject.agent
0 siblings, 0 replies; 16+ messages in thread
From: linuxtestproject.agent @ 2026-10-13 11:27 UTC (permalink / raw)
To: Gaurav Pathak; +Cc: ltp
Hi Gaurav,
On 12 Oct 2026, Gaurav Pathak wrote:
> syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
> #if HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
>
> #if HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
High: These probes inspect libc's struct statx, but buff.data is the
unconditionally extended statx_fallback. With glibc 2.39, a valid atomic
write response yields two TCONF results and no limit checks. Remove both
HAVE_* guards and the new, unnecessary configure probes; detect support
at runtime.
> if (!(buff.data.stx_attributes & STATX_ATTR_WRITE_ATOMIC))
> tst_brk(TCONF, "Filesystem does not support STATX_WRITE_ATOMIC");
Medium: Valid-looking limits pass even with stx_mask and
stx_attributes_mask both zero, while nonzero advertised limits with a
missing active attribute produce only TCONF. Validate both masks before
interpreting the fields, and report inconsistent advertised support as
TFAIL rather than skipping it.
> TST_EXP_PASS_SILENT(SAFE_STATX(AT_FDCWD, TESTFILE, 0, STATX_BASIC_STATS | STATX_WRITE_ATOMIC, &buff));
Medium: SAFE_STATX aborts with TBROK before the expectation can classify
a syscall failure; returning -1/EIO reproduces this. Since statx is the
syscall under test, call statx(..., &buff.buff) directly inside
TST_EXP_PASS_SILENT.
> struct ltp_statx buff;
Low: Allocate the tested syscall output through .bufs using a static
struct ltp_statx pointer and .size = sizeof(*buff), rather than a stack
struct, as required for new LTP tests.
> * It ensures that supported filesystems (xfs and nfs) correctly report their
> * atomic write limits to user space when queried via statx().
Low: The filesystem array tests xfs and ext4, not nfs. Describe the
actual coverage using :manpage:`statx(2)`, and document that root is
required to format and mount the test device.
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] 16+ messages in thread
end of thread, other threads:[~2026-10-13 11:27 UTC | newest]
Thread overview: 16+ 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
2026-10-12 7:23 ` [LTP] [PATCH v4 0/1] " Gaurav Pathak
2026-10-12 7:23 ` [LTP] [PATCH v4 1/1] " Gaurav Pathak
2026-10-12 12:43 ` Andrea Cervesato via ltp
2026-10-13 9:07 ` [LTP] [PATCH v5] " Gaurav Pathak
2026-10-13 11:27 ` [LTP] " linuxtestproject.agent
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.