From c3177bd82c16429c1bb246d19af76012479f0c01 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 31 May 2026 19:04:44 +0300 Subject: getxattrat: READ-classify return for xattr-get family consistency getxattrat(2) (Linux 6.13+) returns the xattr value size in bytes, exactly like getxattr/lgetxattr/fgetxattr, 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). Path extraction (args[1], after the dirfd) and the name-not-captured-as-path behaviour were already correct. Update the docs ReadClassified list and the retclassify expectation, and add the first xattr integration coverage: an ioworkload scenario that sets then getxattrat-reads a user xattr on tmpfs, plus a test that asserts enter_getxattrat captures the file path (not the xattr name) and accounts the returned value size as read bytes. Co-Authored-By: Claude Opus 4.8 --- integrationtests/xattr_test.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 integrationtests/xattr_test.go (limited to 'integrationtests') diff --git a/integrationtests/xattr_test.go b/integrationtests/xattr_test.go new file mode 100644 index 0000000..d36043c --- /dev/null +++ b/integrationtests/xattr_test.go @@ -0,0 +1,37 @@ +package integrationtests + +import "testing" + +// xattrTraceArgs restricts tracing to the getxattrat tracepoints so the test is +// not perturbed by unrelated xattr/open traffic. +var xattrTraceArgs = []string{"-trace-syscalls", "getxattrat,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 +// captured. The path is read on syscall entry, so enter_getxattrat must carry +// the file path "xattrfile.txt" and never the xattr name "user.ior". +func TestXattrGetxattrat(t *testing.T) { + result, _ := runScenarioResultWithIorArgs(t, "xattr-getxattrat", []ExpectedEvent{ + { + PathContains: "xattrfile.txt", + Tracepoint: "enter_getxattrat", + Comm: "ioworkload", + MinCount: 1, + }, + }, xattrTraceArgs) + + // The captured path must be the filesystem path, never the xattr name. + for _, rec := range result.Records { + if rec.TraceID.String() == "enter_getxattrat" && rec.Path == "user.ior" { + t.Errorf("getxattrat captured xattr name %q as path instead of file path", rec.Path) + } + } + + // getxattrat returns the xattr value size in bytes; ior READ-classifies the + // exit, so the recorded byte count must reflect the 16-byte value written by + // the workload (consistent with getxattr/lgetxattr/fgetxattr). + exp := ExpectedEvent{Tracepoint: "enter_getxattrat", Comm: "ioworkload"} + assertEventBytesAtLeast(t, result, exp, uint64(len("getxattrat-value"))) + assertEventDurationPositive(t, result, exp) +} -- cgit v1.2.3