summaryrefslogtreecommitdiff
path: root/integrationtests
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-31 19:09:16 +0300
committerPaul Buetow <paul@buetow.org>2026-05-31 19:09:16 +0300
commit8a1bf6236f6a525881c647fd881093b393436411 (patch)
tree0fb537b847b6e5c72d2d3d98d7ce8fbc15330102 /integrationtests
parentc3177bd82c16429c1bb246d19af76012479f0c01 (diff)
listxattrat: READ-classify return for xattr-list family consistency
listxattrat(2) (Linux 6.13+) returns the size in bytes of the list of extended attribute names, exactly like listxattr/llistxattr/flistxattr, but its exit was classified UNCLASSIFIED, so its read bytes were dropped from I/O totals. Classify it as ReadClassified and regenerate the BPF handler (ret_type now READ_CLASSIFIED). This mirrors the getxattrat fix (task ku, commit c3177bd) and completes xattr-family consistency: get-family and list-family are READ_CLASSIFIED while set-family and remove-family stay UNCLASSIFIED (they return 0/-1). Update the docs ReadClassified list and the retclassify expectation, and add an ioworkload scenario plus integration test: the workload sets a user xattr then lists names via the raw listxattrat(2) syscall with AT_FDCWD, and the test asserts enter_listxattrat captures the file path and accounts the returned name-list size as read bytes. Task: r20 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'integrationtests')
-rw-r--r--integrationtests/xattr_test.go27
1 files changed, 27 insertions, 0 deletions
diff --git a/integrationtests/xattr_test.go b/integrationtests/xattr_test.go
index d36043c..2ba30ac 100644
--- a/integrationtests/xattr_test.go
+++ b/integrationtests/xattr_test.go
@@ -6,6 +6,10 @@ import "testing"
// not perturbed by unrelated xattr/open traffic.
var xattrTraceArgs = []string{"-trace-syscalls", "getxattrat,setxattr,openat"}
+// xattrListTraceArgs restricts tracing to the listxattrat tracepoints so the
+// test is not perturbed by unrelated xattr/open traffic.
+var xattrListTraceArgs = []string{"-trace-syscalls", "listxattrat,setxattr,openat"}
+
// TestXattrGetxattrat verifies ior traces getxattrat(2) (Linux 6.13+)
// end-to-end. getxattrat takes a dirfd plus a real filesystem path at args[1]
// (NOT args[0]=dfd) and an xattr NAME at args[3]; only the path must be
@@ -35,3 +39,26 @@ func TestXattrGetxattrat(t *testing.T) {
assertEventBytesAtLeast(t, result, exp, uint64(len("getxattrat-value")))
assertEventDurationPositive(t, result, exp)
}
+
+// TestXattrListxattrat verifies ior traces listxattrat(2) (Linux 6.13+)
+// end-to-end. listxattrat takes a dirfd plus a real filesystem path at args[1]
+// (NOT args[0]=dfd); only the path must be captured. The path is read on
+// syscall entry, so enter_listxattrat must carry the file path "xattrfile.txt".
+func TestXattrListxattrat(t *testing.T) {
+ result, _ := runScenarioResultWithIorArgs(t, "xattr-listxattrat", []ExpectedEvent{
+ {
+ PathContains: "xattrfile.txt",
+ Tracepoint: "enter_listxattrat",
+ Comm: "ioworkload",
+ MinCount: 1,
+ },
+ }, xattrListTraceArgs)
+
+ // listxattrat returns the size in bytes of the xattr name list; ior
+ // READ-classifies the exit, so the recorded byte count must reflect at least
+ // the NUL-terminated "user.ior" name set by the workload (consistent with
+ // listxattr/llistxattr/flistxattr).
+ exp := ExpectedEvent{Tracepoint: "enter_listxattrat", Comm: "ioworkload"}
+ assertEventBytesAtLeast(t, result, exp, uint64(len("user.ior")+1))
+ assertEventDurationPositive(t, result, exp)
+}