* [LTP] [PATCH v7] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
@ 2026-10-16 7:13 Gaurav Pathak
2026-10-16 10:52 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 8+ messages in thread
From: Gaurav Pathak @ 2026-10-16 7:13 UTC (permalink / raw)
To: Linux Test Project; +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>
---
include/lapi/stat.h | 17 +++-
runtest/syscalls | 1 +
testcases/kernel/syscalls/statx/.gitignore | 1 +
testcases/kernel/syscalls/statx/statx13.c | 138 +++++++++++++++++++++++++++++
4 files changed, 156 insertions(+), 1 deletion(-)
diff --git a/include/lapi/stat.h b/include/lapi/stat.h
index 17b62ea98d6776fafc8713e710093f3c8cf41fc4..859e410ab5cd5560cda49594c77ca87522ae1143 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 accdf2df9b36a0b839a4611b2c231be8d79f4db7..c0d8eb31ec53805244c629611ce26b3cf414508f 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 f6a423eed84dd67152e6f75809037c92ceb1e060..e601a46a352562fb67836a5f78e19e49323f9bf4 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 0000000000000000000000000000000000000000..cf94568e601d9f8cef67d7e2da51027538d6c2a7
--- /dev/null
+++ b/testcases/kernel/syscalls/statx/statx13.c
@@ -0,0 +1,138 @@
+// 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 ext4) correctly report their
+ * atomic write limits to user space when queried via statx().
+ *
+ * Minimum Linux version required is v6.12.
+ */
+
+#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 struct ltp_statx *buff;
+
+static void verify_statx(void)
+{
+ 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);
+
+ if (!TST_PASS)
+ return;
+
+ /* 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_res(TFAIL, "Inconsistent: stx_mask has STATX_WRITE_ATOMIC but stx_attributes_mask lacks STATX_ATTR_WRITE_ATOMIC");
+ return;
+ }
+
+ /* Check if the file/device actively supports atomic writes */
+ if (!(buff->data.stx_attributes & STATX_ATTR_WRITE_ATOMIC)) {
+ if (buff->data.stx_atomic_write_unit_min || buff->data.stx_atomic_write_unit_max ||
+ buff->data.stx_atomic_write_unit_max_opt || buff->data.stx_atomic_write_segments_max) {
+ tst_res(TFAIL,
+ "Inconsistent: STATX_ATTR_WRITE_ATOMIC unset but limits nonzero (min=%u max=%u opt=%u segs=%u)",
+ buff->data.stx_atomic_write_unit_min, buff->data.stx_atomic_write_unit_max,
+ buff->data.stx_atomic_write_unit_max_opt, buff->data.stx_atomic_write_segments_max);
+ return;
+ }
+
+ tst_brk(TCONF, "STATX_WRITE_ATOMIC unsupported by block dev or filesystem: STATX_ATTR_WRITE_ATOMIC missing from stx_attributes");
+ }
+
+ TST_EXP_EXPR(buff->data.stx_atomic_write_unit_min <= buff->data.stx_atomic_write_unit_max,
+ "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);
+
+ TST_EXP_EXPR(buff->data.stx_atomic_write_segments_max > 0,
+ "stx_atomic_write_segments_max(%u) > 0", buff->data.stx_atomic_write_segments_max);
+
+ TST_EXP_EXPR(buff->data.stx_atomic_write_unit_min > 0 &&
+ __builtin_popcount(buff->data.stx_atomic_write_unit_min) == 1,
+ "stx_atomic_write_unit_min(%u) is a power of 2",
+ buff->data.stx_atomic_write_unit_min);
+
+ TST_EXP_EXPR(buff->data.stx_atomic_write_unit_max > 0 &&
+ __builtin_popcount(buff->data.stx_atomic_write_unit_max) == 1,
+ "stx_atomic_write_unit_max(%u) is 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);
+
+ TST_EXP_EXPR(__builtin_popcount(buff->data.stx_atomic_write_unit_max_opt) == 1,
+ "stx_atomic_write_unit_max_opt(%u) is 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,
+ .bufs = (struct tst_buffers []) {
+ {&buff, .size = sizeof(*buff)},
+ {}
+ },
+ .filesystems = (struct tst_fs[]) {
+ {
+ .type = "xfs",
+ .min_kver = "6.12",
+ .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL},
+ },
+ {
+ .type = "ext4",
+ .mkfs_opts = (const char *const []){"-O", "bigalloc", "-b", "4096", "-C", "65536", NULL},
+ },
+ {}
+ },
+};
---
base-commit: 07da37cf3dbda876b33ad820168a33b9deacbddb
change-id: 20261016-statx-atomic-write-cf0c15e273f4
Best regards,
--
Gaurav Pathak <gaurav.pathak@suse.com>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-16 7:13 [LTP] [PATCH v7] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file Gaurav Pathak
@ 2026-10-16 10:52 ` linuxtestproject.agent
0 siblings, 0 replies; 8+ messages in thread
From: linuxtestproject.agent @ 2026-10-16 10:52 UTC (permalink / raw)
To: Gaurav Pathak; +Cc: ltp
Hi Gaurav,
On Fri, 16 Oct 2026, Gaurav Pathak wrote:
> syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
> +++ b/testcases/kernel/syscalls/statx/statx13.c
> + .type = "xfs",
> + .min_kver = "6.12",
> + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL},
With 4 KiB pages and CONFIG_TRANSPARENT_HUGEPAGE disabled, XFS rejects
this 16 KiB filesystem with ENOSYS even on kernels newer than 6.12.
mapping_max_folio_size_supported() returns PAGE_SIZE in that configuration,
so SAFE_MOUNT2 reports TBROK before the statx checks run.
Use the default XFS block size, or gate the large-block configuration on
its actual prerequisites.
> + * This test validates the STATX_WRITE_ATOMIC feature (introduced in Linux 6.13).
> + * It ensures that supported filesystems (xfs and ext4) correctly report their
> + * atomic write limits to user space when queried via statx().
> + *
> + * Minimum Linux version required is v6.12.
STATX_WRITE_ATOMIC was introduced in 6.11 for block devices; regular-file
reporting on XFS/ext4 arrived in 6.13, so the stated 6.12 minimum is
incorrect. Describe the regular-file support explicitly, correct or remove
the minimum-version sentence, and use :manpage:`statx(2)` for the syscall
reference.
> + .needs_root = 1,
Document in the high-level description that root is required to format
and mount the test filesystems.
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] 8+ messages in thread
* [LTP] [PATCH v6] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-13 11:27 ` [LTP] " linuxtestproject.agent
@ 2026-10-14 6:20 Gaurav Pathak
2026-10-14 7:52 ` [LTP] " linuxtestproject.agent
-1 siblings, 1 reply; 8+ messages in thread
From: Gaurav Pathak @ 2026-10-14 6:20 UTC (permalink / raw)
To: ltp; +Cc: Gaurav Pathak, linuxtestproject.agent
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>
---
include/lapi/stat.h | 17 ++-
runtest/syscalls | 1 +
testcases/kernel/syscalls/statx/.gitignore | 1 +
testcases/kernel/syscalls/statx/statx13.c | 130 +++++++++++++++++++++
4 files changed, 148 insertions(+), 1 deletion(-)
create mode 100644 testcases/kernel/syscalls/statx/statx13.c
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..4b717e27e
--- /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 and ext4) 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 struct ltp_statx *buff;
+
+static void verify_statx(void)
+{
+ 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_res(TFAIL, "Inconsistent: stx_mask has STATX_WRITE_ATOMIC but stx_attributes_mask lacks STATX_ATTR_WRITE_ATOMIC");
+ return;
+ }
+
+ /* 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,
+ .bufs = (struct tst_buffers []) {
+ {&buff, .size = sizeof(*buff)},
+ {}
+ },
+ .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] 8+ messages in thread* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-10-14 6:20 [LTP] [PATCH v6] " Gaurav Pathak
@ 2026-10-14 7:52 ` linuxtestproject.agent
0 siblings, 0 replies; 8+ messages in thread
From: linuxtestproject.agent @ 2026-10-14 7:52 UTC (permalink / raw)
To: Gaurav Pathak; +Cc: ltp
Hi Gaurav,
On 13 Oct 2026, Gaurav Pathak wrote:
> syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
> + 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);
TST_EXP_PASS reports failure but does not return, so a statx() error leaves
the following checks reading uninitialized output. Return immediately when
!TST_PASS before accessing buff. Allocate this syscall buffer through .bufs
rather than on the stack.
> + .min_kver = "6.11",
> ...
> + .type = "xfs",
> + .mkfs_opts = (const char *const []){"-f", "-bsize=16K", NULL},
Linux 6.11 rejects XFS blocks larger than PAGE_SIZE, so this configuration
fails to mount on a 4 KiB-page system admitted by min_kver. The framework
reports TBROK before setup or feature detection, also preventing the ext4
case from running. Use a portable block size or separately gate this
large-block configuration.
> + 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");
A response with nonzero atomic limits but a missing support attribute is
inconsistent, not simply unsupported. This branch hides that regression as
TCONF despite the stated goal of validating the attribute. Check
attribute/limit consistency first and reserve TCONF for unsupported results
with zero limits.
> + uint32_t stx_atomic_write_segments_max; \
verify_statx() never checks this returned limit. A response advertising
atomic writes with segments_max = 0 passes every assertion, although it
cannot describe a nonempty atomic write. Require
stx_atomic_write_segments_max > 0 when support is advertised.
> + 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);
Use TST_EXP_EXPR for this comparison and the repeated power-of-two
assertions instead of manual TPASS/TFAIL branches.
> + * It ensures that supported filesystems (xfs and nfs) correctly report their
> + * atomic write limits to user space when queried via statx().
The filesystem list tests XFS and ext4, not NFS. Describe the actual
regular-file checks using :manpage:`statx(2)` and document that root is
required to format and mount the test filesystems.
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] 8+ messages in thread
* [LTP] [PATCH v5] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
@ 2026-10-13 9:07 Gaurav Pathak
2026-10-13 11:27 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 8+ 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] 8+ 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; 8+ 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] 8+ messages in thread
* [LTP] [PATCH v3] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
@ 2026-09-18 11:12 Gaurav Pathak
2026-09-18 12:51 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 8+ 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] 8+ 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; 8+ 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] 8+ messages in thread
* [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-09-17 2:56 [LTP] [PATCH] " Gaurav Pathak
@ 2026-09-17 10:53 Gaurav Pathak
2026-09-17 11:17 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 8+ 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] 8+ messages in thread* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-09-17 10:53 [LTP] [PATCH] " Gaurav Pathak
@ 2026-09-17 11:17 ` linuxtestproject.agent
0 siblings, 0 replies; 8+ 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] 8+ messages in thread
* [LTP] [PATCH] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
@ 2026-09-17 2:56 Gaurav Pathak
2026-09-17 11:15 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 8+ 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] 8+ messages in thread* Re: [LTP] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file
2026-09-17 2:56 [LTP] [PATCH] " Gaurav Pathak
@ 2026-09-17 11:15 ` linuxtestproject.agent
0 siblings, 0 replies; 8+ 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] 8+ messages in thread
end of thread, other threads:[~2026-10-16 10:52 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 7:13 [LTP] [PATCH v7] syscalls/statx13: Add basic test for STATX_WRITE_ATOMIC on regular file Gaurav Pathak
2026-10-16 10:52 ` [LTP] " linuxtestproject.agent
-- strict thread matches above, loose matches on Subject: below --
2026-10-14 6:20 [LTP] [PATCH v6] " Gaurav Pathak
2026-10-14 7:52 ` [LTP] " linuxtestproject.agent
2026-10-13 9:07 [LTP] [PATCH v5] " Gaurav Pathak
2026-10-13 11:27 ` [LTP] " linuxtestproject.agent
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-09-17 10:53 [LTP] [PATCH] " Gaurav Pathak
2026-09-17 11:17 ` [LTP] " linuxtestproject.agent
2026-09-17 2:56 [LTP] [PATCH] " Gaurav Pathak
2026-09-17 11:15 ` [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.