diff options
| -rw-r--r-- | IDEAS.md | 2 | ||||
| -rw-r--r-- | Magefile.go | 40 | ||||
| -rw-r--r-- | integrationtests/attach_tracepoints_test.go | 59 | ||||
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenario_copy_file_range.go | 78 | ||||
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenarios.go | 2 | ||||
| -rw-r--r-- | integrationtests/copy_file_range_test.go | 25 | ||||
| -rw-r--r-- | integrationtests/harness.go | 15 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints.c | 48 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints_result.txt | 3 | ||||
| -rw-r--r-- | internal/eventloop.go | 4 | ||||
| -rw-r--r-- | internal/eventloop_test.go | 93 | ||||
| -rw-r--r-- | internal/flags/flags.go | 2 | ||||
| -rw-r--r-- | internal/generate/classify.go | 4 | ||||
| -rw-r--r-- | internal/generate/classify_test.go | 2 | ||||
| -rw-r--r-- | internal/generate/testdata.go | 33 | ||||
| -rw-r--r-- | internal/ior.go | 43 | ||||
| -rw-r--r-- | internal/ior_test.go | 101 | ||||
| -rw-r--r-- | internal/tracepoints/generated_tracepoints.go | 2 | ||||
| -rw-r--r-- | internal/types/generated_types.go | 6 |
19 files changed, 539 insertions, 23 deletions
@@ -1,4 +1,4 @@ -# TODO's +# Ideas ## FlameGraphs diff --git a/Magefile.go b/Magefile.go index 00d2be7..33db267 100644 --- a/Magefile.go +++ b/Magefile.go @@ -89,6 +89,20 @@ func TestWithName() error { if testName == "" { testName = "TestEventloop" } + isIntegration, err := isIntegrationTest(testName) + if err != nil { + return err + } + if isIntegration { + mg.SerialDeps(All) + if err := buildWorkloadBinary(); err != nil { + return err + } + fmt.Println("Running integration test", testName, "(requires root)...") + env := goEnv() + forwardEnv(env, "HOME", "GOPATH", "GOMODCACHE", "PATH") + return sudoRunWithEnv(env, "go", "test", "./integrationtests/...", "-run", "^"+testName+"$", "-v", "-failfast", "-count=1") + } return sh.RunWithV(goEnv(), "go", "test", "./...", "-run", "^"+testName+"$", "-v", "-failfast") } @@ -243,9 +257,8 @@ func World() error { // IntegrationTest builds everything and runs integration tests with sudo. func IntegrationTest() error { mg.SerialDeps(All) - fmt.Println("Building ioworkload binary...") - if err := sh.RunV("go", "build", "-o", workloadBinaryName, workloadSourcePath); err != nil { - return fmt.Errorf("build ioworkload: %w", err) + if err := buildWorkloadBinary(); err != nil { + return err } fmt.Println("Running integration tests (requires root)...") env := goEnv() @@ -253,6 +266,14 @@ func IntegrationTest() error { return sudoRunWithEnv(env, "go", "test", "./integrationtests/...", "-v", "-failfast", "-count=1") } +func buildWorkloadBinary() error { + fmt.Println("Building ioworkload binary...") + if err := sh.RunWithV(goEnv(), "go", "build", "-o", workloadBinaryName, workloadSourcePath); err != nil { + return fmt.Errorf("build ioworkload: %w", err) + } + return nil +} + // Prof generates CPU and memory profiling PDFs. func Prof() error { if err := runShellCommand("go tool pprof -pdf ./ior ior.cpuprofile > cpuprofile.pdf"); err != nil { @@ -512,3 +533,16 @@ func sortLinesWithLocale(lines []string) (string, error) { } return string(output), nil } + +func isIntegrationTest(testName string) (bool, error) { + out, err := sh.OutputWith(goEnv(), "go", "test", "./integrationtests/...", "-list", ".") + if err != nil { + return false, fmt.Errorf("list integration tests: %w", err) + } + for _, line := range strings.Split(out, "\n") { + if strings.TrimSpace(line) == testName { + return true, nil + } + } + return false, nil +} diff --git a/integrationtests/attach_tracepoints_test.go b/integrationtests/attach_tracepoints_test.go new file mode 100644 index 0000000..89db494 --- /dev/null +++ b/integrationtests/attach_tracepoints_test.go @@ -0,0 +1,59 @@ +package integrationtests + +import "testing" + +func TestAttachTracepointsIncludeFilter(t *testing.T) { + h := newTestHarness(t) + + // Only load openat tracepoints so write events from the workload are not captured. + result, pid, err := h.RunWithIorArgs("open-rdonly-write", defaultDuration, []string{ + "-tps", "^sys_enter_openat$,^sys_exit_openat$", + }) + if err != nil { + t.Fatalf("run scenario open-rdonly-write with include filter: %v", err) + } + + AssertNoUnexpectedPID(t, result, pid) + AssertNoUnexpectedComm(t, result, "ioworkload") + AssertEventsPresent(t, result, []ExpectedEvent{ + { + PathContains: "rdonlyfile.txt", + Tracepoint: "enter_openat", + Comm: "ioworkload", + MinCount: 1, + }, + }) + AssertEventsAbsent(t, result, []ExpectedEvent{ + { + PathContains: "rdonlyfile.txt", + Tracepoint: "enter_write", + Comm: "ioworkload", + }, + }) +} + +func TestAttachTracepointsExcludeByInclusion(t *testing.T) { + h := newTestHarness(t) + + // Negative case: include only write tracepoints; openat must not be captured. + result, pid, err := h.RunWithIorArgs("open-rdonly-write", defaultDuration, []string{ + "-tps", "^sys_enter_write$,^sys_exit_write$", + }) + if err != nil { + t.Fatalf("run scenario open-rdonly-write with write-only include filter: %v", err) + } + + AssertNoUnexpectedPID(t, result, pid) + AssertNoUnexpectedComm(t, result, "ioworkload") + AssertEventsPresent(t, result, []ExpectedEvent{ + { + Tracepoint: "enter_write", + MinCount: 1, + }, + }) + AssertEventsAbsent(t, result, []ExpectedEvent{ + { + Tracepoint: "enter_openat", + }, + }) +} diff --git a/integrationtests/cmd/ioworkload/scenario_copy_file_range.go b/integrationtests/cmd/ioworkload/scenario_copy_file_range.go new file mode 100644 index 0000000..87531b0 --- /dev/null +++ b/integrationtests/cmd/ioworkload/scenario_copy_file_range.go @@ -0,0 +1,78 @@ +package main + +import ( + "fmt" + "path/filepath" + "syscall" +) + +// SYS_COPY_FILE_RANGE on x86_64 Linux. +const sysCopyFileRange = 326 + +// copyFileRangeBasic copies bytes from a source file to a destination file +// using copy_file_range(2) with flags=0 as required by the manpage. +func copyFileRangeBasic() error { + dir, cleanup, err := makeTempDir("copy-file-range-basic") + if err != nil { + return err + } + defer cleanup() + + srcPath := filepath.Join(dir, "copyrangesrc.txt") + dstPath := filepath.Join(dir, "copyrangedst.txt") + + srcFd, err := syscall.Open(srcPath, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open source: %w", err) + } + defer syscall.Close(srcFd) + + dstFd, err := syscall.Open(dstPath, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open destination: %w", err) + } + defer syscall.Close(dstFd) + + data := []byte("copy_file_range integration data") + if _, err := syscall.Write(srcFd, data); err != nil { + return fmt.Errorf("write source: %w", err) + } + + n, _, errno := syscall.Syscall6(uintptr(sysCopyFileRange), uintptr(srcFd), 0, uintptr(dstFd), 0, uintptr(len(data)), 0) + if errno != 0 { + return fmt.Errorf("copy_file_range: %w", errno) + } + if n == 0 { + return fmt.Errorf("copy_file_range copied 0 bytes") + } + + return nil +} + +// copyFileRangeBadDstFd calls copy_file_range(2) with an invalid destination fd. +// The syscall should fail with EBADF, while still emitting the enter tracepoint. +func copyFileRangeBadDstFd() error { + dir, cleanup, err := makeTempDir("copy-file-range-bad-dst") + if err != nil { + return err + } + defer cleanup() + + srcPath := filepath.Join(dir, "copyrangeebadfsrc.txt") + srcFd, err := syscall.Open(srcPath, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open source: %w", err) + } + defer syscall.Close(srcFd) + + if _, err := syscall.Write(srcFd, []byte("copy_file_range ebadf data")); err != nil { + return fmt.Errorf("write source: %w", err) + } + + _, _, errno := syscall.Syscall6(uintptr(sysCopyFileRange), uintptr(srcFd), 0, uintptr(99999), 0, uintptr(16), 0) + if errno != syscall.EBADF { + return fmt.Errorf("expected EBADF from copy_file_range with invalid dst fd, got %v", errno) + } + + return nil +} diff --git a/integrationtests/cmd/ioworkload/scenarios.go b/integrationtests/cmd/ioworkload/scenarios.go index d99b584..f9a8e47 100644 --- a/integrationtests/cmd/ioworkload/scenarios.go +++ b/integrationtests/cmd/ioworkload/scenarios.go @@ -85,6 +85,8 @@ var scenarios = map[string]func() error{ "mmap-basic": mmapBasic, "mmap-msync-sync": mmapMsyncSync, "mmap-msync-invalid-flags": mmapMsyncInvalidFlags, + "copy-file-range-basic": copyFileRangeBasic, + "copy-file-range-bad-dst-fd": copyFileRangeBadDstFd, "truncate-basic": truncateBasic, "truncate-ftruncate": truncateFtruncate, "truncate-enoent": truncateEnoent, diff --git a/integrationtests/copy_file_range_test.go b/integrationtests/copy_file_range_test.go new file mode 100644 index 0000000..d87c5af --- /dev/null +++ b/integrationtests/copy_file_range_test.go @@ -0,0 +1,25 @@ +package integrationtests + +import "testing" + +func TestCopyFileRangeBasic(t *testing.T) { + runScenario(t, "copy-file-range-basic", []ExpectedEvent{ + { + PathContains: "copyrangesrc.txt", + Tracepoint: "enter_copy_file_range", + Comm: "ioworkload", + MinCount: 1, + }, + }) +} + +func TestCopyFileRangeBadDstFd(t *testing.T) { + runScenario(t, "copy-file-range-bad-dst-fd", []ExpectedEvent{ + { + PathContains: "copyrangeebadfsrc.txt", + Tracepoint: "enter_copy_file_range", + Comm: "ioworkload", + MinCount: 1, + }, + }) +} diff --git a/integrationtests/harness.go b/integrationtests/harness.go index fde52e6..a130c85 100644 --- a/integrationtests/harness.go +++ b/integrationtests/harness.go @@ -30,12 +30,17 @@ type TestHarness struct { // binary, reads its PID from stdout, launches ior with a PID filter, waits // for both to finish, and parses the resulting .ior.zst file. func (h *TestHarness) Run(scenario string, duration int) (TestResult, int, error) { + return h.RunWithIorArgs(scenario, duration, nil) +} + +// RunWithIorArgs behaves like Run but forwards additional args to ior. +func (h *TestHarness) RunWithIorArgs(scenario string, duration int, extraIorArgs []string) (TestResult, int, error) { workloadCmd, workloadPID, err := h.startWorkload(scenario) if err != nil { return TestResult{}, 0, err } - iorCmd, err := h.startIor(workloadPID, scenario, duration) + iorCmd, err := h.startIor(workloadPID, scenario, duration, extraIorArgs) if err != nil { workloadCmd.Process.Kill() workloadCmd.Wait() @@ -111,18 +116,20 @@ func (h *TestHarness) startWorkload(scenario string) (*exec.Cmd, int, error) { } } -func (h *TestHarness) startIor(pid int, scenario string, duration int) (*exec.Cmd, error) { +func (h *TestHarness) startIor(pid int, scenario string, duration int, extraArgs []string) (*exec.Cmd, error) { bpfLink := filepath.Join(h.OutputDir, "ior.bpf.o") if err := os.Symlink(h.BpfObject, bpfLink); err != nil { return nil, fmt.Errorf("symlink bpf object: %w", err) } - cmd := exec.Command(h.IorBinary, + args := []string{ "-pid", strconv.Itoa(pid), "-flamegraph", "-name", scenario, "-duration", strconv.Itoa(duration), - ) + } + args = append(args, extraArgs...) + cmd := exec.Command(h.IorBinary, args...) cmd.Dir = h.OutputDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/internal/c/generated_tracepoints.c b/internal/c/generated_tracepoints.c index 72cb070..9f62fd8 100644 --- a/internal/c/generated_tracepoints.c +++ b/internal/c/generated_tracepoints.c @@ -20,7 +20,6 @@ /// Ignoring sys_enter_clone sys_exit_clone as possibly not file I/O related /// Ignoring sys_enter_clone3 sys_exit_clone3 as possibly not file I/O related /// Ignoring sys_enter_connect sys_exit_connect as possibly not file I/O related -/// Ignoring sys_enter_copy_file_range sys_exit_copy_file_range as possibly not file I/O related /// Ignoring sys_enter_delete_module sys_exit_delete_module as possibly not file I/O related /// Ignoring sys_enter_epoll_create sys_exit_epoll_create as possibly not file I/O related /// Ignoring sys_enter_epoll_create1 sys_exit_epoll_create1 as possibly not file I/O related @@ -423,6 +422,8 @@ #define SYS_EXIT_PWRITEV 827 #define SYS_ENTER_PWRITEV2 826 #define SYS_EXIT_PWRITEV2 825 +#define SYS_ENTER_COPY_FILE_RANGE 822 +#define SYS_EXIT_COPY_FILE_RANGE 821 #define SYS_ENTER_TRUNCATE 820 #define SYS_EXIT_TRUNCATE 819 #define SYS_ENTER_FTRUNCATE 818 @@ -4354,6 +4355,51 @@ int handle_sys_exit_pwritev2(struct trace_event_raw_sys_exit *ctx) { return 0; } +/// sys_enter_copy_file_range is a struct fd_event +SEC("tracepoint/syscalls/sys_enter_copy_file_range") +int handle_sys_enter_copy_file_range(struct trace_event_raw_sys_enter *ctx) { + __u32 pid, tid; + if (filter(&pid, &tid)) + return 0; + + struct fd_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct fd_event), 0); + if (!ev) + return 0; + + ev->event_type = ENTER_FD_EVENT; + ev->trace_id = SYS_ENTER_COPY_FILE_RANGE; + ev->pid = pid; + ev->tid = tid; + ev->time = bpf_ktime_get_boot_ns(); + ev->fd = (__s32)ctx->args[0]; + + bpf_ringbuf_submit(ev, 0); + return 0; +} + +/// sys_exit_copy_file_range is a struct ret_event (TRANSFER_CLASSIFIED) +SEC("tracepoint/syscalls/sys_exit_copy_file_range") +int handle_sys_exit_copy_file_range(struct trace_event_raw_sys_exit *ctx) { + __u32 pid, tid; + if (filter(&pid, &tid)) + return 0; + + struct ret_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct ret_event), 0); + if (!ev) + return 0; + + ev->event_type = EXIT_RET_EVENT; + ev->trace_id = SYS_EXIT_COPY_FILE_RANGE; + ev->pid = pid; + ev->tid = tid; + ev->time = bpf_ktime_get_boot_ns(); + ev->ret = ctx->ret; + ev->ret_type = TRANSFER_CLASSIFIED; + + bpf_ringbuf_submit(ev, 0); + return 0; +} + /// sys_enter_truncate is a struct path_event SEC("tracepoint/syscalls/sys_enter_truncate") int handle_sys_enter_truncate(struct trace_event_raw_sys_enter *ctx) { diff --git a/internal/c/generated_tracepoints_result.txt b/internal/c/generated_tracepoints_result.txt index 357d279..e3fdd55 100644 --- a/internal/c/generated_tracepoints_result.txt +++ b/internal/c/generated_tracepoints_result.txt @@ -18,7 +18,6 @@ Ignoring sys_enter_clock_settime sys_exit_clock_settime as possibly not file I/O Ignoring sys_enter_clone sys_exit_clone as possibly not file I/O related Ignoring sys_enter_clone3 sys_exit_clone3 as possibly not file I/O related Ignoring sys_enter_connect sys_exit_connect as possibly not file I/O related -Ignoring sys_enter_copy_file_range sys_exit_copy_file_range as possibly not file I/O related Ignoring sys_enter_delete_module sys_exit_delete_module as possibly not file I/O related Ignoring sys_enter_epoll_create sys_exit_epoll_create as possibly not file I/O related Ignoring sys_enter_epoll_create1 sys_exit_epoll_create1 as possibly not file I/O related @@ -258,6 +257,7 @@ sys_enter_chown is a struct path_event sys_enter_chroot is a struct path_event sys_enter_close is a struct fd_event sys_enter_close_range is a struct fd_event +sys_enter_copy_file_range is a struct fd_event sys_enter_creat is a struct path_event sys_enter_dup is a struct fd_event sys_enter_dup2 is a struct fd_event @@ -372,6 +372,7 @@ sys_exit_chown is a struct ret_event (UNCLASSIFIED) sys_exit_chroot is a struct ret_event (UNCLASSIFIED) sys_exit_close is a struct ret_event (UNCLASSIFIED) sys_exit_close_range is a struct ret_event (UNCLASSIFIED) +sys_exit_copy_file_range is a struct ret_event (TRANSFER_CLASSIFIED) sys_exit_creat is a struct ret_event (UNCLASSIFIED) sys_exit_dup is a struct ret_event (UNCLASSIFIED) sys_exit_dup2 is a struct ret_event (UNCLASSIFIED) diff --git a/internal/eventloop.go b/internal/eventloop.go index 451e8ae..7bfd576 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -417,10 +417,6 @@ func (e *eventLoop) tracepointExited(exitEv event.Event, ch chan<- *event.Pair) default: panic(fmt.Sprintf("unknown type: %v", v)) } - // TODO: implement copy_file_range - // TODO: open_by_handle_at - // TODO: getcwd? - prevPairTime, _ := e.prevPairTimes[ep.EnterEv.GetTid()] ep.CalculateDurations(prevPairTime) e.prevPairTimes[ep.EnterEv.GetTid()] = ep.ExitEv.GetTime() diff --git a/internal/eventloop_test.go b/internal/eventloop_test.go index ca82f55..319e6c7 100644 --- a/internal/eventloop_test.go +++ b/internal/eventloop_test.go @@ -37,6 +37,7 @@ func TestEventloop(t *testing.T) { "CloseRangeFailureTest": makeCloseRangeFailureTestData(t), "FsyncEventTest": makeFsyncEventTestData(t), "SyncFileRangeEventTest": makeSyncFileRangeEventTestData(t), + "CopyFileRangeEventTest": makeCopyFileRangeEventTestData(t), "MmapEventTest": makeMmapEventTestData(t), "MsyncEventTest": makeMsyncEventTestData(t), "FtruncateEventTest": makeFtruncateEventTestData(t), @@ -645,6 +646,98 @@ func makeSyncFileRangeEventTestData(t *testing.T) (td testData) { return td } +func makeCopyFileRangeEventTestData(t *testing.T) (td testData) { + srcFd := int32(49) + dstFd := int32(50) + srcName := "copy_file_range_src.txt" + dstName := "copy_file_range_dst.txt" + copiedBytes := int64(21) + + srcOpenEnter, _ := makeEnterOpenEvent(t, defaulTime, defaultPid, defaultTid) + copy(srcOpenEnter.Filename[:], srcName) + srcOpenEnterBytes, err := srcOpenEnter.Bytes() + if err != nil { + t.Fatal(err) + } + td.rawTracepoints = append(td.rawTracepoints, srcOpenEnterBytes) + + srcOpenExit, _ := makeExitOpenEvent(t, defaulTime+100, defaultPid, defaultTid) + srcOpenExit.Ret = int64(srcFd) + srcOpenExitBytes, err := srcOpenExit.Bytes() + if err != nil { + t.Fatal(err) + } + td.rawTracepoints = append(td.rawTracepoints, srcOpenExitBytes) + + dstOpenEnter, _ := makeEnterOpenEvent(t, defaulTime+200, defaultPid, defaultTid) + copy(dstOpenEnter.Filename[:], dstName) + dstOpenEnterBytes, err := dstOpenEnter.Bytes() + if err != nil { + t.Fatal(err) + } + td.rawTracepoints = append(td.rawTracepoints, dstOpenEnterBytes) + + dstOpenExit, _ := makeExitOpenEvent(t, defaulTime+300, defaultPid, defaultTid) + dstOpenExit.Ret = int64(dstFd) + dstOpenExitBytes, err := dstOpenExit.Bytes() + if err != nil { + t.Fatal(err) + } + td.rawTracepoints = append(td.rawTracepoints, dstOpenExitBytes) + + copyEnter, copyEnterBytes := makeEnterFdEvent(t, defaulTime+400, defaultPid, defaultTid, srcFd, types.SYS_ENTER_COPY_FILE_RANGE) + td.rawTracepoints = append(td.rawTracepoints, copyEnterBytes) + + copyExit := types.RetEvent{ + EventType: types.EXIT_RET_EVENT, + TraceId: types.SYS_EXIT_COPY_FILE_RANGE, + Time: defaulTime + 500, + Ret: copiedBytes, + Pid: defaultPid, + Tid: defaultTid, + RetType: types.TRANSFER_CLASSIFIED, + } + copyExitBytes, err := copyExit.Bytes() + if err != nil { + t.Fatal(err) + } + td.rawTracepoints = append(td.rawTracepoints, copyExitBytes) + + td.validates = append(td.validates, func(t *testing.T, el *eventLoop, ep *event.Pair) { + if !srcOpenEnter.Equals(ep.EnterEv) || !srcOpenExit.Equals(ep.ExitEv) { + t.Errorf("unexpected src open event pair: %v", ep) + } + verifyFileDescriptor(t, el, srcFd, srcName) + }) + + td.validates = append(td.validates, func(t *testing.T, el *eventLoop, ep *event.Pair) { + if !dstOpenEnter.Equals(ep.EnterEv) || !dstOpenExit.Equals(ep.ExitEv) { + t.Errorf("unexpected dst open event pair: %v", ep) + } + verifyFileDescriptor(t, el, dstFd, dstName) + }) + + td.validates = append(td.validates, func(t *testing.T, el *eventLoop, ep *event.Pair) { + if !copyEnter.Equals(ep.EnterEv) { + t.Errorf("Expected '%v' but got '%v'", copyEnter, ep.EnterEv) + } + if !copyExit.Equals(ep.ExitEv) { + t.Errorf("Expected '%v' but got '%v'", copyExit, ep.ExitEv) + } + if ep.File == nil { + t.Fatalf("Expected copy_file_range event to carry source file metadata") + } + if ep.File.Name() != srcName { + t.Errorf("Expected source file '%s' but got '%s'", srcName, ep.File.Name()) + } + if ep.Bytes != uint64(copiedBytes) { + t.Errorf("Expected copied bytes %d but got %d", copiedBytes, ep.Bytes) + } + }) + + return td +} + func makeMmapEventTestData(t *testing.T) (td testData) { fd := int32(48) filename := "mmap_test.txt" diff --git a/internal/flags/flags.go b/internal/flags/flags.go index eb2d045..2aec752 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -110,7 +110,7 @@ func parse() { // disabledTracepoints is a list of tracepoints that should not be attached due to wider isses. // Here, the BPF programs wouldn't load otherwise due to CO-RE issues. - // TODO: Try out once in a while whether it works again with newer kernel versions. + // Re-evaluate periodically on newer kernels. // Add back "._open_by_handle_at" or ".*_name_to_handle_at" here if tracepoints cause CO-RE issues. if *fields == "" { diff --git a/internal/generate/classify.go b/internal/generate/classify.go index b79d49c..ae03758 100644 --- a/internal/generate/classify.go +++ b/internal/generate/classify.go @@ -142,6 +142,10 @@ func classifyNameAndField(name, fieldType, fieldName string) (ClassificationResu if fieldType == "const char *" && fieldName == "name" { return ClassificationResult{Kind: KindPathname, PathnameField: "name"}, true } + case "sys_enter_copy_file_range": + if isFdType(fieldType) && fieldName == "fd_in" { + return ClassificationResult{Kind: KindFd}, true + } } if strings.HasPrefix(name, "sys_enter") && diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go index 285c8e2..8d6f9c2 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -272,6 +272,7 @@ func TestShouldNotIgnore(t *testing.T) { noIgnore := []string{ "sys_enter_read", "sys_enter_write", "sys_enter_openat", "sys_enter_close", "sys_enter_rename", "sys_enter_unlink", + "sys_enter_copy_file_range", "sys_enter_msync", "sys_exit_read", "sys_exit_openat", } @@ -299,6 +300,7 @@ func TestClassifySyscallPairAccepted(t *testing.T) { {"fcntl", FormatFcntl, FormatExitFcntl, KindFcntl}, {"sync", FormatSync, FormatExitSync, KindNull}, {"msync", FormatMsync, FormatExitMsync, KindNull}, + {"copy_file_range", FormatCopyFileRange, FormatExitCopyFileRange, KindFd}, {"syslog", FormatSyslog, FormatExitSyslog, KindNull}, {"open_by_handle_at", FormatOpenByHandleAt, FormatExitOpenByHandleAt, KindOpenByHandleAt}, {"name_to_handle_at", FormatNameToHandleAt, FormatExitNameToHandleAt, KindPathname}, diff --git a/internal/generate/testdata.go b/internal/generate/testdata.go index c03c0d7..76228a3 100644 --- a/internal/generate/testdata.go +++ b/internal/generate/testdata.go @@ -182,6 +182,39 @@ format: print fmt: "0x%lx", REC->ret ` +const FormatCopyFileRange = `name: sys_enter_copy_file_range +ID: 736 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:int fd_in; offset:16; size:8; signed:0; + field:loff_t * off_in; offset:24; size:8; signed:0; + field:int fd_out; offset:32; size:8; signed:0; + field:loff_t * off_out; offset:40; size:8; signed:0; + field:size_t len; offset:48; size:8; signed:0; + field:unsigned int flags; offset:56; size:8; signed:0; + +print fmt: "fd_in: 0x%08lx, off_in: 0x%08lx, fd_out: 0x%08lx, off_out: 0x%08lx, len: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->fd_in)), ((unsigned long)(REC->off_in)), ((unsigned long)(REC->fd_out)), ((unsigned long)(REC->off_out)), ((unsigned long)(REC->len)), ((unsigned long)(REC->flags)) +` + +const FormatExitCopyFileRange = `name: sys_exit_copy_file_range +ID: 735 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + const FormatRename = `name: sys_enter_rename ID: 870 format: diff --git a/internal/ior.go b/internal/ior.go index f06b730..0299539 100644 --- a/internal/ior.go +++ b/internal/ior.go @@ -18,22 +18,53 @@ import ( bpf "github.com/aquasecurity/libbpfgo" ) -// TODO: Generally, write unit tests -// TODO: Integration tests, write C or Cgo code to simulate I/O? +type tracepointProgram interface { + attachTracepoint(category, name string) error +} + +type tracepointModule interface { + getProgram(progName string) (tracepointProgram, error) +} + +type libbpfTracepointProgram struct { + prog *bpf.BPFProg +} + +func (p libbpfTracepointProgram) attachTracepoint(category, name string) error { + _, err := p.prog.AttachTracepoint(category, name) + return err +} + +type libbpfTracepointModule struct { + module *bpf.Module +} + +func (m libbpfTracepointModule) getProgram(progName string) (tracepointProgram, error) { + prog, err := m.module.GetProgram(progName) + if err != nil { + return nil, err + } + return libbpfTracepointProgram{prog: prog}, nil +} + func attachTracepoints(bpfModule *bpf.Module) error { - for _, name := range tracepoints.List { - if !flags.Get().ShouldIAttachTracepoint(name) { + return attachTracepointsWith(libbpfTracepointModule{module: bpfModule}, flags.Get().ShouldIAttachTracepoint, tracepoints.List) +} + +func attachTracepointsWith(module tracepointModule, shouldAttach func(string) bool, tracepointNames []string) error { + for _, name := range tracepointNames { + if !shouldAttach(name) { continue } fmt.Println("Attaching tracepoint", name) - prog, err := bpfModule.GetProgram(fmt.Sprintf("handle_%s", name)) + prog, err := module.getProgram(fmt.Sprintf("handle_%s", name)) if err != nil { return fmt.Errorf("Failed to get BPF program handle_%s: %v", name, err) } fmt.Println("Attached prog handle_", name) - if _, err = prog.AttachTracepoint("syscalls", name); err != nil { + if err = prog.attachTracepoint("syscalls", name); err != nil { // OK, older Kernel versions may not have this tracepoint! fmt.Printf("Failed to attach to %s tracepoint: %v, kernel version may be too old, skipping", name, err) continue diff --git a/internal/ior_test.go b/internal/ior_test.go new file mode 100644 index 0000000..6495e76 --- /dev/null +++ b/internal/ior_test.go @@ -0,0 +1,101 @@ +package internal + +import ( + "errors" + "strings" + "testing" +) + +type fakeTracepointProgram struct { + attachCalls int + attachErr error +} + +func (p *fakeTracepointProgram) attachTracepoint(_, _ string) error { + p.attachCalls++ + return p.attachErr +} + +type fakeTracepointModule struct { + getProgramCalls []string + getProgramErrs map[string]error + programs map[string]*fakeTracepointProgram +} + +func (m *fakeTracepointModule) getProgram(progName string) (tracepointProgram, error) { + m.getProgramCalls = append(m.getProgramCalls, progName) + if err, ok := m.getProgramErrs[progName]; ok { + return nil, err + } + if prog, ok := m.programs[progName]; ok { + return prog, nil + } + return nil, errors.New("missing program") +} + +func TestAttachTracepointsWithSkipsFilteredTracepoints(t *testing.T) { + module := &fakeTracepointModule{ + programs: map[string]*fakeTracepointProgram{ + "handle_sys_enter_read": {}, + "handle_sys_enter_write": {}, + }, + getProgramErrs: map[string]error{}, + } + + err := attachTracepointsWith(module, func(tracepoint string) bool { + return tracepoint == "sys_enter_read" + }, []string{"sys_enter_read", "sys_enter_write"}) + if err != nil { + t.Fatalf("attachTracepointsWith returned error: %v", err) + } + + if len(module.getProgramCalls) != 1 || module.getProgramCalls[0] != "handle_sys_enter_read" { + t.Fatalf("getProgram calls = %v, want only handle_sys_enter_read", module.getProgramCalls) + } + + if module.programs["handle_sys_enter_read"].attachCalls != 1 { + t.Fatalf("read attach calls = %d, want 1", module.programs["handle_sys_enter_read"].attachCalls) + } + if module.programs["handle_sys_enter_write"].attachCalls != 0 { + t.Fatalf("write attach calls = %d, want 0", module.programs["handle_sys_enter_write"].attachCalls) + } +} + +func TestAttachTracepointsWithReturnsErrorWhenProgramMissing(t *testing.T) { + module := &fakeTracepointModule{ + programs: map[string]*fakeTracepointProgram{}, + getProgramErrs: map[string]error{ + "handle_sys_enter_read": errors.New("not found"), + }, + } + + err := attachTracepointsWith(module, func(string) bool { return true }, []string{"sys_enter_read"}) + if err == nil { + t.Fatal("attachTracepointsWith returned nil error, want non-nil") + } + if !strings.Contains(err.Error(), "handle_sys_enter_read") { + t.Fatalf("error %q does not mention handle_sys_enter_read", err) + } +} + +func TestAttachTracepointsWithAttachFailureContinues(t *testing.T) { + module := &fakeTracepointModule{ + programs: map[string]*fakeTracepointProgram{ + "handle_sys_enter_read": {attachErr: errors.New("no tracepoint")}, + "handle_sys_enter_write": {}, + }, + getProgramErrs: map[string]error{}, + } + + err := attachTracepointsWith(module, func(string) bool { return true }, []string{"sys_enter_read", "sys_enter_write"}) + if err != nil { + t.Fatalf("attachTracepointsWith returned error: %v", err) + } + + if module.programs["handle_sys_enter_read"].attachCalls != 1 { + t.Fatalf("read attach calls = %d, want 1", module.programs["handle_sys_enter_read"].attachCalls) + } + if module.programs["handle_sys_enter_write"].attachCalls != 1 { + t.Fatalf("write attach calls = %d, want 1", module.programs["handle_sys_enter_write"].attachCalls) + } +} diff --git a/internal/tracepoints/generated_tracepoints.go b/internal/tracepoints/generated_tracepoints.go index c81dd9c..b0e44ac 100644 --- a/internal/tracepoints/generated_tracepoints.go +++ b/internal/tracepoints/generated_tracepoints.go @@ -172,6 +172,8 @@ var List = []string{ "sys_exit_pwritev", "sys_enter_pwritev2", "sys_exit_pwritev2", + "sys_enter_copy_file_range", + "sys_exit_copy_file_range", "sys_enter_truncate", "sys_exit_truncate", "sys_enter_ftruncate", diff --git a/internal/types/generated_types.go b/internal/types/generated_types.go index c0e3ecb..eb11e5b 100644 --- a/internal/types/generated_types.go +++ b/internal/types/generated_types.go @@ -12,11 +12,11 @@ type EventType uint32 type TraceId uint32 var traceId2String = map[TraceId]string{ - 1515: "enter_io_uring_register", 1514: "exit_io_uring_register", 1496: "enter_io_uring_enter", 1495: "exit_io_uring_enter", 1494: "enter_io_uring_setup", 1493: "exit_io_uring_setup", 1151: "enter_quotactl_fd", 1150: "exit_quotactl_fd", 1135: "enter_name_to_handle_at", 1134: "exit_name_to_handle_at", 1133: "enter_open_by_handle_at", 1132: "exit_open_by_handle_at", 1119: "enter_flock", 1118: "exit_flock", 1105: "enter_io_setup", 1104: "exit_io_setup", 1103: "enter_io_destroy", 1102: "exit_io_destroy", 1101: "enter_io_submit", 1100: "exit_io_submit", 1099: "enter_io_cancel", 1098: "exit_io_cancel", 1097: "enter_io_getevents", 1096: "exit_io_getevents", 1095: "enter_io_pgetevents", 1094: "exit_io_pgetevents", 1063: "enter_fanotify_mark", 1062: "exit_fanotify_mark", 1053: "enter_file_getattr", 1052: "exit_file_getattr", 1051: "enter_file_setattr", 1050: "exit_file_setattr", 1047: "enter_fspick", 1046: "exit_fspick", 1045: "enter_fsconfig", 1044: "exit_fsconfig", 1043: "enter_statfs", 1042: "exit_statfs", 1041: "enter_fstatfs", 1040: "exit_fstatfs", 1035: "enter_utimensat", 1034: "exit_utimensat", 1033: "enter_futimesat", 1032: "exit_futimesat", 1027: "enter_sync", 1026: "exit_sync", 1025: "enter_syncfs", 1024: "exit_syncfs", 1023: "enter_fsync", 1022: "exit_fsync", 1021: "enter_fdatasync", 1020: "exit_fdatasync", 1019: "enter_sync_file_range", 1018: "exit_sync_file_range", 1017: "enter_vmsplice", 1016: "exit_vmsplice", 978: "enter_setxattrat", 977: "exit_setxattrat", 976: "enter_setxattr", 975: "exit_setxattr", 974: "enter_lsetxattr", 973: "exit_lsetxattr", 972: "enter_fsetxattr", 971: "exit_fsetxattr", 970: "enter_getxattrat", 969: "exit_getxattrat", 968: "enter_getxattr", 967: "exit_getxattr", 966: "enter_lgetxattr", 965: "exit_lgetxattr", 964: "enter_fgetxattr", 963: "exit_fgetxattr", 962: "enter_listxattrat", 961: "exit_listxattrat", 960: "enter_listxattr", 959: "exit_listxattr", 958: "enter_llistxattr", 957: "exit_llistxattr", 956: "enter_flistxattr", 955: "exit_flistxattr", 954: "enter_removexattrat", 953: "exit_removexattrat", 952: "enter_removexattr", 951: "exit_removexattr", 950: "enter_lremovexattr", 949: "exit_lremovexattr", 948: "enter_fremovexattr", 947: "exit_fremovexattr", 944: "enter_open_tree", 943: "exit_open_tree", 934: "enter_mount_setattr", 933: "exit_mount_setattr", 932: "enter_open_tree_attr", 931: "exit_open_tree_attr", 924: "enter_close_range", 923: "exit_close_range", 922: "enter_dup3", 921: "exit_dup3", 920: "enter_dup2", 919: "exit_dup2", 918: "enter_dup", 917: "exit_dup", 904: "enter_getdents", 903: "exit_getdents", 902: "enter_getdents64", 901: "exit_getdents64", 900: "enter_ioctl", 899: "exit_ioctl", 898: "enter_fcntl", 897: "exit_fcntl", 892: "enter_mkdirat", 891: "exit_mkdirat", 890: "enter_mkdir", 889: "exit_mkdir", 888: "enter_rmdir", 887: "exit_rmdir", 886: "enter_unlinkat", 885: "exit_unlinkat", 884: "enter_unlink", 883: "exit_unlink", 882: "enter_symlinkat", 881: "exit_symlinkat", 880: "enter_symlink", 879: "exit_symlink", 878: "enter_linkat", 877: "exit_linkat", 876: "enter_link", 875: "exit_link", 874: "enter_renameat2", 873: "exit_renameat2", 872: "enter_renameat", 871: "exit_renameat", 870: "enter_rename", 869: "exit_rename", 860: "enter_newstat", 859: "exit_newstat", 858: "enter_newlstat", 857: "exit_newlstat", 856: "enter_newfstatat", 855: "exit_newfstatat", 854: "enter_newfstat", 853: "exit_newfstat", 852: "enter_readlinkat", 851: "exit_readlinkat", 850: "enter_readlink", 849: "exit_readlink", 848: "enter_statx", 847: "exit_statx", 846: "enter_lseek", 845: "exit_lseek", 844: "enter_read", 843: "exit_read", 842: "enter_write", 841: "exit_write", 840: "enter_pread64", 839: "exit_pread64", 838: "enter_pwrite64", 837: "exit_pwrite64", 836: "enter_readv", 835: "exit_readv", 834: "enter_writev", 833: "exit_writev", 832: "enter_preadv", 831: "exit_preadv", 830: "enter_preadv2", 829: "exit_preadv2", 828: "enter_pwritev", 827: "exit_pwritev", 826: "enter_pwritev2", 825: "exit_pwritev2", 820: "enter_truncate", 819: "exit_truncate", 818: "enter_ftruncate", 817: "exit_ftruncate", 816: "enter_fallocate", 815: "exit_fallocate", 814: "enter_faccessat", 813: "exit_faccessat", 812: "enter_faccessat2", 811: "exit_faccessat2", 810: "enter_access", 809: "exit_access", 808: "enter_chdir", 807: "exit_chdir", 806: "enter_fchdir", 805: "exit_fchdir", 804: "enter_chroot", 803: "exit_chroot", 802: "enter_fchmod", 801: "exit_fchmod", 800: "enter_fchmodat2", 799: "exit_fchmodat2", 798: "enter_fchmodat", 797: "exit_fchmodat", 796: "enter_chmod", 795: "exit_chmod", 794: "enter_fchownat", 793: "exit_fchownat", 792: "enter_chown", 791: "exit_chown", 790: "enter_lchown", 789: "exit_lchown", 788: "enter_fchown", 787: "exit_fchown", 786: "enter_open", 785: "exit_open", 784: "enter_openat", 783: "exit_openat", 782: "enter_openat2", 781: "exit_openat2", 780: "enter_creat", 779: "exit_creat", 778: "enter_close", 777: "exit_close", 707: "enter_msync", 706: "exit_msync", 613: "enter_readahead", 612: "exit_readahead", 611: "enter_fadvise64", 610: "exit_fadvise64", 592: "enter_cachestat", 591: "exit_cachestat", 403: "enter_finit_module", 402: "exit_finit_module", 347: "enter_syslog", 346: "exit_syslog", 100: "enter_mmap", 99: "exit_mmap", + 1515: "enter_io_uring_register", 1514: "exit_io_uring_register", 1496: "enter_io_uring_enter", 1495: "exit_io_uring_enter", 1494: "enter_io_uring_setup", 1493: "exit_io_uring_setup", 1151: "enter_quotactl_fd", 1150: "exit_quotactl_fd", 1135: "enter_name_to_handle_at", 1134: "exit_name_to_handle_at", 1133: "enter_open_by_handle_at", 1132: "exit_open_by_handle_at", 1119: "enter_flock", 1118: "exit_flock", 1105: "enter_io_setup", 1104: "exit_io_setup", 1103: "enter_io_destroy", 1102: "exit_io_destroy", 1101: "enter_io_submit", 1100: "exit_io_submit", 1099: "enter_io_cancel", 1098: "exit_io_cancel", 1097: "enter_io_getevents", 1096: "exit_io_getevents", 1095: "enter_io_pgetevents", 1094: "exit_io_pgetevents", 1063: "enter_fanotify_mark", 1062: "exit_fanotify_mark", 1053: "enter_file_getattr", 1052: "exit_file_getattr", 1051: "enter_file_setattr", 1050: "exit_file_setattr", 1047: "enter_fspick", 1046: "exit_fspick", 1045: "enter_fsconfig", 1044: "exit_fsconfig", 1043: "enter_statfs", 1042: "exit_statfs", 1041: "enter_fstatfs", 1040: "exit_fstatfs", 1035: "enter_utimensat", 1034: "exit_utimensat", 1033: "enter_futimesat", 1032: "exit_futimesat", 1027: "enter_sync", 1026: "exit_sync", 1025: "enter_syncfs", 1024: "exit_syncfs", 1023: "enter_fsync", 1022: "exit_fsync", 1021: "enter_fdatasync", 1020: "exit_fdatasync", 1019: "enter_sync_file_range", 1018: "exit_sync_file_range", 1017: "enter_vmsplice", 1016: "exit_vmsplice", 978: "enter_setxattrat", 977: "exit_setxattrat", 976: "enter_setxattr", 975: "exit_setxattr", 974: "enter_lsetxattr", 973: "exit_lsetxattr", 972: "enter_fsetxattr", 971: "exit_fsetxattr", 970: "enter_getxattrat", 969: "exit_getxattrat", 968: "enter_getxattr", 967: "exit_getxattr", 966: "enter_lgetxattr", 965: "exit_lgetxattr", 964: "enter_fgetxattr", 963: "exit_fgetxattr", 962: "enter_listxattrat", 961: "exit_listxattrat", 960: "enter_listxattr", 959: "exit_listxattr", 958: "enter_llistxattr", 957: "exit_llistxattr", 956: "enter_flistxattr", 955: "exit_flistxattr", 954: "enter_removexattrat", 953: "exit_removexattrat", 952: "enter_removexattr", 951: "exit_removexattr", 950: "enter_lremovexattr", 949: "exit_lremovexattr", 948: "enter_fremovexattr", 947: "exit_fremovexattr", 944: "enter_open_tree", 943: "exit_open_tree", 934: "enter_mount_setattr", 933: "exit_mount_setattr", 932: "enter_open_tree_attr", 931: "exit_open_tree_attr", 924: "enter_close_range", 923: "exit_close_range", 922: "enter_dup3", 921: "exit_dup3", 920: "enter_dup2", 919: "exit_dup2", 918: "enter_dup", 917: "exit_dup", 904: "enter_getdents", 903: "exit_getdents", 902: "enter_getdents64", 901: "exit_getdents64", 900: "enter_ioctl", 899: "exit_ioctl", 898: "enter_fcntl", 897: "exit_fcntl", 892: "enter_mkdirat", 891: "exit_mkdirat", 890: "enter_mkdir", 889: "exit_mkdir", 888: "enter_rmdir", 887: "exit_rmdir", 886: "enter_unlinkat", 885: "exit_unlinkat", 884: "enter_unlink", 883: "exit_unlink", 882: "enter_symlinkat", 881: "exit_symlinkat", 880: "enter_symlink", 879: "exit_symlink", 878: "enter_linkat", 877: "exit_linkat", 876: "enter_link", 875: "exit_link", 874: "enter_renameat2", 873: "exit_renameat2", 872: "enter_renameat", 871: "exit_renameat", 870: "enter_rename", 869: "exit_rename", 860: "enter_newstat", 859: "exit_newstat", 858: "enter_newlstat", 857: "exit_newlstat", 856: "enter_newfstatat", 855: "exit_newfstatat", 854: "enter_newfstat", 853: "exit_newfstat", 852: "enter_readlinkat", 851: "exit_readlinkat", 850: "enter_readlink", 849: "exit_readlink", 848: "enter_statx", 847: "exit_statx", 846: "enter_lseek", 845: "exit_lseek", 844: "enter_read", 843: "exit_read", 842: "enter_write", 841: "exit_write", 840: "enter_pread64", 839: "exit_pread64", 838: "enter_pwrite64", 837: "exit_pwrite64", 836: "enter_readv", 835: "exit_readv", 834: "enter_writev", 833: "exit_writev", 832: "enter_preadv", 831: "exit_preadv", 830: "enter_preadv2", 829: "exit_preadv2", 828: "enter_pwritev", 827: "exit_pwritev", 826: "enter_pwritev2", 825: "exit_pwritev2", 822: "enter_copy_file_range", 821: "exit_copy_file_range", 820: "enter_truncate", 819: "exit_truncate", 818: "enter_ftruncate", 817: "exit_ftruncate", 816: "enter_fallocate", 815: "exit_fallocate", 814: "enter_faccessat", 813: "exit_faccessat", 812: "enter_faccessat2", 811: "exit_faccessat2", 810: "enter_access", 809: "exit_access", 808: "enter_chdir", 807: "exit_chdir", 806: "enter_fchdir", 805: "exit_fchdir", 804: "enter_chroot", 803: "exit_chroot", 802: "enter_fchmod", 801: "exit_fchmod", 800: "enter_fchmodat2", 799: "exit_fchmodat2", 798: "enter_fchmodat", 797: "exit_fchmodat", 796: "enter_chmod", 795: "exit_chmod", 794: "enter_fchownat", 793: "exit_fchownat", 792: "enter_chown", 791: "exit_chown", 790: "enter_lchown", 789: "exit_lchown", 788: "enter_fchown", 787: "exit_fchown", 786: "enter_open", 785: "exit_open", 784: "enter_openat", 783: "exit_openat", 782: "enter_openat2", 781: "exit_openat2", 780: "enter_creat", 779: "exit_creat", 778: "enter_close", 777: "exit_close", 707: "enter_msync", 706: "exit_msync", 613: "enter_readahead", 612: "exit_readahead", 611: "enter_fadvise64", 610: "exit_fadvise64", 592: "enter_cachestat", 591: "exit_cachestat", 403: "enter_finit_module", 402: "exit_finit_module", 347: "enter_syslog", 346: "exit_syslog", 100: "enter_mmap", 99: "exit_mmap", } var traceId2Name = map[TraceId]string{ - 1515: "io_uring_register", 1514: "io_uring_register", 1496: "io_uring_enter", 1495: "io_uring_enter", 1494: "io_uring_setup", 1493: "io_uring_setup", 1151: "quotactl_fd", 1150: "quotactl_fd", 1135: "name_to_handle_at", 1134: "name_to_handle_at", 1133: "open_by_handle_at", 1132: "open_by_handle_at", 1119: "flock", 1118: "flock", 1105: "io_setup", 1104: "io_setup", 1103: "io_destroy", 1102: "io_destroy", 1101: "io_submit", 1100: "io_submit", 1099: "io_cancel", 1098: "io_cancel", 1097: "io_getevents", 1096: "io_getevents", 1095: "io_pgetevents", 1094: "io_pgetevents", 1063: "fanotify_mark", 1062: "fanotify_mark", 1053: "file_getattr", 1052: "file_getattr", 1051: "file_setattr", 1050: "file_setattr", 1047: "fspick", 1046: "fspick", 1045: "fsconfig", 1044: "fsconfig", 1043: "statfs", 1042: "statfs", 1041: "fstatfs", 1040: "fstatfs", 1035: "utimensat", 1034: "utimensat", 1033: "futimesat", 1032: "futimesat", 1027: "sync", 1026: "sync", 1025: "syncfs", 1024: "syncfs", 1023: "fsync", 1022: "fsync", 1021: "fdatasync", 1020: "fdatasync", 1019: "sync_file_range", 1018: "sync_file_range", 1017: "vmsplice", 1016: "vmsplice", 978: "setxattrat", 977: "setxattrat", 976: "setxattr", 975: "setxattr", 974: "lsetxattr", 973: "lsetxattr", 972: "fsetxattr", 971: "fsetxattr", 970: "getxattrat", 969: "getxattrat", 968: "getxattr", 967: "getxattr", 966: "lgetxattr", 965: "lgetxattr", 964: "fgetxattr", 963: "fgetxattr", 962: "listxattrat", 961: "listxattrat", 960: "listxattr", 959: "listxattr", 958: "llistxattr", 957: "llistxattr", 956: "flistxattr", 955: "flistxattr", 954: "removexattrat", 953: "removexattrat", 952: "removexattr", 951: "removexattr", 950: "lremovexattr", 949: "lremovexattr", 948: "fremovexattr", 947: "fremovexattr", 944: "open_tree", 943: "open_tree", 934: "mount_setattr", 933: "mount_setattr", 932: "open_tree_attr", 931: "open_tree_attr", 924: "close_range", 923: "close_range", 922: "dup3", 921: "dup3", 920: "dup2", 919: "dup2", 918: "dup", 917: "dup", 904: "getdents", 903: "getdents", 902: "getdents64", 901: "getdents64", 900: "ioctl", 899: "ioctl", 898: "fcntl", 897: "fcntl", 892: "mkdirat", 891: "mkdirat", 890: "mkdir", 889: "mkdir", 888: "rmdir", 887: "rmdir", 886: "unlinkat", 885: "unlinkat", 884: "unlink", 883: "unlink", 882: "symlinkat", 881: "symlinkat", 880: "symlink", 879: "symlink", 878: "linkat", 877: "linkat", 876: "link", 875: "link", 874: "renameat2", 873: "renameat2", 872: "renameat", 871: "renameat", 870: "rename", 869: "rename", 860: "newstat", 859: "newstat", 858: "newlstat", 857: "newlstat", 856: "newfstatat", 855: "newfstatat", 854: "newfstat", 853: "newfstat", 852: "readlinkat", 851: "readlinkat", 850: "readlink", 849: "readlink", 848: "statx", 847: "statx", 846: "lseek", 845: "lseek", 844: "read", 843: "read", 842: "write", 841: "write", 840: "pread64", 839: "pread64", 838: "pwrite64", 837: "pwrite64", 836: "readv", 835: "readv", 834: "writev", 833: "writev", 832: "preadv", 831: "preadv", 830: "preadv2", 829: "preadv2", 828: "pwritev", 827: "pwritev", 826: "pwritev2", 825: "pwritev2", 820: "truncate", 819: "truncate", 818: "ftruncate", 817: "ftruncate", 816: "fallocate", 815: "fallocate", 814: "faccessat", 813: "faccessat", 812: "faccessat2", 811: "faccessat2", 810: "access", 809: "access", 808: "chdir", 807: "chdir", 806: "fchdir", 805: "fchdir", 804: "chroot", 803: "chroot", 802: "fchmod", 801: "fchmod", 800: "fchmodat2", 799: "fchmodat2", 798: "fchmodat", 797: "fchmodat", 796: "chmod", 795: "chmod", 794: "fchownat", 793: "fchownat", 792: "chown", 791: "chown", 790: "lchown", 789: "lchown", 788: "fchown", 787: "fchown", 786: "open", 785: "open", 784: "openat", 783: "openat", 782: "openat2", 781: "openat2", 780: "creat", 779: "creat", 778: "close", 777: "close", 707: "msync", 706: "msync", 613: "readahead", 612: "readahead", 611: "fadvise64", 610: "fadvise64", 592: "cachestat", 591: "cachestat", 403: "finit_module", 402: "finit_module", 347: "syslog", 346: "syslog", 100: "mmap", 99: "mmap", + 1515: "io_uring_register", 1514: "io_uring_register", 1496: "io_uring_enter", 1495: "io_uring_enter", 1494: "io_uring_setup", 1493: "io_uring_setup", 1151: "quotactl_fd", 1150: "quotactl_fd", 1135: "name_to_handle_at", 1134: "name_to_handle_at", 1133: "open_by_handle_at", 1132: "open_by_handle_at", 1119: "flock", 1118: "flock", 1105: "io_setup", 1104: "io_setup", 1103: "io_destroy", 1102: "io_destroy", 1101: "io_submit", 1100: "io_submit", 1099: "io_cancel", 1098: "io_cancel", 1097: "io_getevents", 1096: "io_getevents", 1095: "io_pgetevents", 1094: "io_pgetevents", 1063: "fanotify_mark", 1062: "fanotify_mark", 1053: "file_getattr", 1052: "file_getattr", 1051: "file_setattr", 1050: "file_setattr", 1047: "fspick", 1046: "fspick", 1045: "fsconfig", 1044: "fsconfig", 1043: "statfs", 1042: "statfs", 1041: "fstatfs", 1040: "fstatfs", 1035: "utimensat", 1034: "utimensat", 1033: "futimesat", 1032: "futimesat", 1027: "sync", 1026: "sync", 1025: "syncfs", 1024: "syncfs", 1023: "fsync", 1022: "fsync", 1021: "fdatasync", 1020: "fdatasync", 1019: "sync_file_range", 1018: "sync_file_range", 1017: "vmsplice", 1016: "vmsplice", 978: "setxattrat", 977: "setxattrat", 976: "setxattr", 975: "setxattr", 974: "lsetxattr", 973: "lsetxattr", 972: "fsetxattr", 971: "fsetxattr", 970: "getxattrat", 969: "getxattrat", 968: "getxattr", 967: "getxattr", 966: "lgetxattr", 965: "lgetxattr", 964: "fgetxattr", 963: "fgetxattr", 962: "listxattrat", 961: "listxattrat", 960: "listxattr", 959: "listxattr", 958: "llistxattr", 957: "llistxattr", 956: "flistxattr", 955: "flistxattr", 954: "removexattrat", 953: "removexattrat", 952: "removexattr", 951: "removexattr", 950: "lremovexattr", 949: "lremovexattr", 948: "fremovexattr", 947: "fremovexattr", 944: "open_tree", 943: "open_tree", 934: "mount_setattr", 933: "mount_setattr", 932: "open_tree_attr", 931: "open_tree_attr", 924: "close_range", 923: "close_range", 922: "dup3", 921: "dup3", 920: "dup2", 919: "dup2", 918: "dup", 917: "dup", 904: "getdents", 903: "getdents", 902: "getdents64", 901: "getdents64", 900: "ioctl", 899: "ioctl", 898: "fcntl", 897: "fcntl", 892: "mkdirat", 891: "mkdirat", 890: "mkdir", 889: "mkdir", 888: "rmdir", 887: "rmdir", 886: "unlinkat", 885: "unlinkat", 884: "unlink", 883: "unlink", 882: "symlinkat", 881: "symlinkat", 880: "symlink", 879: "symlink", 878: "linkat", 877: "linkat", 876: "link", 875: "link", 874: "renameat2", 873: "renameat2", 872: "renameat", 871: "renameat", 870: "rename", 869: "rename", 860: "newstat", 859: "newstat", 858: "newlstat", 857: "newlstat", 856: "newfstatat", 855: "newfstatat", 854: "newfstat", 853: "newfstat", 852: "readlinkat", 851: "readlinkat", 850: "readlink", 849: "readlink", 848: "statx", 847: "statx", 846: "lseek", 845: "lseek", 844: "read", 843: "read", 842: "write", 841: "write", 840: "pread64", 839: "pread64", 838: "pwrite64", 837: "pwrite64", 836: "readv", 835: "readv", 834: "writev", 833: "writev", 832: "preadv", 831: "preadv", 830: "preadv2", 829: "preadv2", 828: "pwritev", 827: "pwritev", 826: "pwritev2", 825: "pwritev2", 822: "copy_file_range", 821: "copy_file_range", 820: "truncate", 819: "truncate", 818: "ftruncate", 817: "ftruncate", 816: "fallocate", 815: "fallocate", 814: "faccessat", 813: "faccessat", 812: "faccessat2", 811: "faccessat2", 810: "access", 809: "access", 808: "chdir", 807: "chdir", 806: "fchdir", 805: "fchdir", 804: "chroot", 803: "chroot", 802: "fchmod", 801: "fchmod", 800: "fchmodat2", 799: "fchmodat2", 798: "fchmodat", 797: "fchmodat", 796: "chmod", 795: "chmod", 794: "fchownat", 793: "fchownat", 792: "chown", 791: "chown", 790: "lchown", 789: "lchown", 788: "fchown", 787: "fchown", 786: "open", 785: "open", 784: "openat", 783: "openat", 782: "openat2", 781: "openat2", 780: "creat", 779: "creat", 778: "close", 777: "close", 707: "msync", 706: "msync", 613: "readahead", 612: "readahead", 611: "fadvise64", 610: "fadvise64", 592: "cachestat", 591: "cachestat", 403: "finit_module", 402: "finit_module", 347: "syslog", 346: "syslog", 100: "mmap", 99: "mmap", } func (s TraceId) String() string { @@ -229,6 +229,8 @@ const SYS_ENTER_PWRITEV TraceId = 828 const SYS_EXIT_PWRITEV TraceId = 827 const SYS_ENTER_PWRITEV2 TraceId = 826 const SYS_EXIT_PWRITEV2 TraceId = 825 +const SYS_ENTER_COPY_FILE_RANGE TraceId = 822 +const SYS_EXIT_COPY_FILE_RANGE TraceId = 821 const SYS_ENTER_TRUNCATE TraceId = 820 const SYS_EXIT_TRUNCATE TraceId = 819 const SYS_ENTER_FTRUNCATE TraceId = 818 |
