diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-30 17:16:09 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-30 17:16:09 +0300 |
| commit | 8b64d566300b7e952da63e11cba7575d7b06e7e2 (patch) | |
| tree | c218d42c3d0bcb027e9cc91410d18f1608d7f408 /internal/generate/retclassify_test.go | |
| parent | e462a4d9963a2949f0670a00a013dd362b5219d1 (diff) | |
test(generate): lock in lseek classification (offset, not byte count)
Audit of lseek(2) confirmed the tracing implementation is already correct:
enter is a KindFd fd_event capturing the fd from args[0], the syscall is
FamilyFS alongside its read/write/fsync siblings, and the exit is a plain
ret_event that stays UNCLASSIFIED. lseek returns the RESULTING file offset
(off_t, bytes from the start of the file), which is a file position, NOT a
count of bytes transferred — so it must never be READ/WRITE/TRANSFER
classified, which would wrongly inflate I/O byte totals.
Add lock-in tests pinning that behaviour so a future reclassification trips:
- FormatLseek/FormatExitLseek tracepoint fixtures.
- TestClassifyFdLseek: enter resolves to KindFd (fd at args[0]).
- TestClassifyRetExitLseek: exit is KindRet and ClassifyRet stays UNCLASSIFIED.
- lseek entry in TestClassifySyscallPairAccepted (end-to-end pair).
- FS-family asserts for sys_enter/exit_lseek in family_test.
- Enriched UNCLASSIFIED comment in retclassify_test explaining offset != bytes.
No generated-artifact changes (mage generate produces no diff); no in-scope
bugs and no out-of-scope follow-ups found.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal/generate/retclassify_test.go')
| -rw-r--r-- | internal/generate/retclassify_test.go | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/internal/generate/retclassify_test.go b/internal/generate/retclassify_test.go index ad548b2..25c5e71 100644 --- a/internal/generate/retclassify_test.go +++ b/internal/generate/retclassify_test.go @@ -42,8 +42,18 @@ func TestClassifyRetTransfer(t *testing.T) { func TestClassifyRetUnclassified(t *testing.T) { unclassified := []string{ "openat", "close", "rename", "unlink", "fcntl", "dup", "dup2", "dup3", - "mkdir", "rmdir", "chmod", "chown", "chdir", "stat", "lseek", + "mkdir", "rmdir", "chmod", "chown", "chdir", "stat", "truncate", "fallocate", "mmap", "fsync", "flock", "recvmmsg", "sendmmsg", + // lseek(2) repositions the file offset of args[0]'s fd and returns the + // RESULTING file OFFSET (off_t, bytes from the start of the file) on + // success, or -1 on error. That return is a file POSITION, NOT a count of + // bytes transferred — so its exit must stay UNCLASSIFIED (plain + // ret_event). Classifying it as READ/WRITE/TRANSFER would wrongly add the + // absolute file position into I/O byte totals and grossly inflate them + // (e.g. an lseek to offset 1 GiB would look like a 1 GiB transfer). lseek + // is a KindFd FamilyFS syscall like its read/write/fsync siblings; only + // read/write actually move bytes and carry a byte-count return. + "lseek", // syncfs(2) returns int 0/-1 (no byte count); it commits the filesystem // containing args[0]'s fd and transfers no bytes, so its exit must stay // UNCLASSIFIED (plain ret_event), like its fsync/fdatasync siblings. |
