this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

wip

+684 -40
+1
.gitignore
··· 5 5 arch 6 6 *.csv 7 7 *.json 8 + *.txt
+11 -2
dune
··· 1 + (menhir 2 + (modules parser)) 3 + 4 + (ocamllex lexer) 5 + 1 6 (executable 2 7 (name opentrace) 3 8 (public_name opentrace) 4 - (modules opentrace config) 9 + (modules opentrace config parser filter lexer spawn) 10 + (foreign_stubs 11 + (language c) 12 + (flags :standard -D_LARGEFILE64_SOURCE) 13 + (names opentrace_stubs)) 5 14 (preprocess 6 15 (pps ppx_blob)) 7 16 (preprocessor_deps 8 17 (file opentrace.bpf.o)) 9 - (libraries eio_main jsonm cmdliner unix libbpf libbpf_maps)) 18 + (libraries eio_posix jsonm cmdliner unix libbpf libbpf_maps)) 10 19 11 20 (rule 12 21 (mode
+1
dune-project
··· 1 1 (lang dune 3.14) 2 + (using menhir 3.0) 2 3 3 4 (name opentrace) 4 5
+3
example/dune
··· 1 + (executable 2 + (name main) 3 + (libraries eio_main))
+5
example/main.ml
··· 1 + let () = 2 + Eio_main.run @@ fun env -> 3 + Eio.Path.(save ~create:(`Or_truncate 0o664) (env#fs / "hello.txt") "hello"); 4 + Eio.Process.run env#process_mgr 5 + [ "/bin/bash"; "-c"; "echo 'heya' > heya.txt" ]
+18
filter.ml
··· 1 + type t = Flag of int | And of t * t | Or of t * t | Not of t 2 + 3 + let rec pp ppf = function 4 + | Flag s -> Fmt.string ppf (Config.to_string s) 5 + | And (e1, e2) -> Fmt.pf ppf "%a&%a" pp e1 pp e2 6 + | Or (e1, e2) -> Fmt.pf ppf "%a|%a" pp e1 pp e2 7 + | Not e1 -> Fmt.pf ppf "~%a" pp e1 8 + 9 + let check_flag i t = Int.equal (t land i) i 10 + 11 + let satisfies (expr : t) flags = 12 + let rec loop = function 13 + | Flag s -> check_flag s flags 14 + | Not e -> not (loop e) 15 + | And (e1, e2) -> loop e1 && loop e2 16 + | Or (e1, e2) -> loop e1 || loop e2 17 + in 18 + loop expr
+20
lexer.mll
··· 1 + { 2 + open Parser 3 + 4 + exception SyntaxError of string 5 + } 6 + 7 + let white = [' ' '\t']+ 8 + let id = ['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '0'-'9' '_']* 9 + 10 + rule read = 11 + parse 12 + | white { read lexbuf } 13 + | id as s { FLAG s } 14 + | '(' { LPAREN } 15 + | ')' { RPAREN } 16 + | '&' { AND } 17 + | '|' { OR } 18 + | '~' { NOT } 19 + | _ { raise (SyntaxError ("Unexpected char: " ^ Lexing.lexeme lexbuf)) } 20 + | eof { EOF }
+101 -7
opentrace.bpf.c
··· 1 1 #include "vmlinux.h" 2 + #include "uring.h" 2 3 #include <bpf/bpf_helpers.h> 4 + #include <bpf/bpf_tracing.h> 5 + #include <bpf/bpf_core_read.h> 3 6 4 7 char LICENSE[] SEC("license") = "Dual BSD/GPL"; 5 8 ··· 16 19 #define OPEN_KIND 0 17 20 #define OPENAT_KIND 1 18 21 #define OPENAT2_KIND 2 22 + #define URING_KIND 3 19 23 20 24 // An open event 21 25 struct open_event ··· 35 39 struct { 36 40 __uint(type, BPF_MAP_TYPE_HASH); 37 41 __uint(max_entries, 10240); 38 - __type(key, u32); // PID 42 + __type(key, u32); // PID/User Data 39 43 __type(value, struct open_event); // The event 40 44 } tmpmap SEC(".maps"); 41 45 ··· 75 79 76 80 // Add it to the hash map 77 81 bpf_map_update_elem(&tmpmap, &pid, &oet, BPF_NOEXIST); 78 - 79 82 return 0; 80 83 } 81 84 ··· 99 102 return 0; 100 103 } 101 104 102 - // SEC("tracepoint/syscalls/sys_exit_open") 103 - // int tracepoint__syscalls__sys_exit_open(struct syscall_trace_exit* ctx) 104 - // { 105 - // return complete_event(OPEN_KIND, ctx); 106 - // } 107 105 108 106 SEC("tracepoint/syscalls/sys_exit_openat") 109 107 int tracepoint__syscalls__sys_exit_openat(struct syscall_trace_exit* ctx) ··· 147 145 SEC("tracepoint/syscalls/sys_exit_openat2") 148 146 int tracepoint__syscalls__sys_exit_openat2(struct syscall_trace_exit* ctx) 149 147 { 148 + struct open_event *ev; 149 + u64 id = bpf_get_current_pid_tgid(); 150 + u32 pid = id >> 32; 151 + 152 + struct open_event *oet; 153 + oet = bpf_ringbuf_reserve(&rb, sizeof(struct open_event), 0); 154 + if (!oet) 155 + return 0; 156 + 157 + // Find our event 158 + ev = bpf_map_lookup_elem(&tmpmap, &pid); 159 + if (!ev) { 160 + // Tidy up 161 + bpf_ringbuf_discard(oet, 0); 162 + bpf_map_delete_elem(&tmpmap, &pid); 163 + return 0; 164 + } 165 + 166 + oet->e_ret = ctx->ret; 167 + oet->e_cgid = bpf_get_current_cgroup_id(); 168 + bpf_probe_read_str(&oet->e_filename, sizeof(oet->e_filename), ev->e_filename); 169 + bpf_get_current_comm(oet->e_comm, TASK_COMM_LEN); 170 + oet->e_flags = ev->e_flags; 171 + oet->e_pid = pid; 172 + oet->e_mode = ev->e_mode; 173 + oet->e_kind = OPENAT2_KIND; 174 + 175 + // Tidy up 176 + bpf_map_delete_elem(&tmpmap, &pid); 177 + 178 + /* emit event */ 179 + bpf_ringbuf_submit(oet, 0); 180 + 150 181 return 0; 151 182 } 183 + 184 + /* IO_URING is not so clean :S */ 185 + SEC("kprobe/io_openat2") 186 + int BPF_KPROBE(trace_io_uring_openat_entry, struct io_kiocb *req, int issue_flags) 187 + { 188 + struct io_open open; 189 + int res = bpf_probe_read(&open, sizeof(open), req); 190 + if (res != 0) { 191 + static const char fmt[] = "openat read failed %i\n"; 192 + bpf_trace_printk(fmt, sizeof(fmt), res); 193 + return 0; 194 + } 195 + struct task_struct *task = (struct task_struct *)bpf_get_current_task_btf(); 196 + char commit[TASK_COMM_LEN]; 197 + 198 + bpf_get_current_comm(&commit, TASK_COMM_LEN); 199 + 200 + u64 pid_tgid = bpf_get_current_pid_tgid(); 201 + 202 + struct open_event oet = {0}; 203 + struct open_how how = {0}; 204 + bpf_probe_read_user(&how, sizeof(how), (void *)&open.how); 205 + oet.e_flags = (int)open.how.flags; 206 + oet.e_mode = (__u32)open.how.mode; 207 + oet.e_filename[0] = '\0'; 208 + 209 + bpf_map_update_elem(&tmpmap, &pid_tgid, &oet, BPF_ANY); 210 + return 0; 211 + } 212 + 213 + // Return probe 214 + SEC("kretprobe/io_openat2") 215 + int BPF_KRETPROBE(trace_io_uring_openat_ret) 216 + { 217 + u64 pid_tgid = bpf_get_current_pid_tgid(); 218 + 219 + struct open_event *ev = bpf_map_lookup_elem(&tmpmap, &pid_tgid); 220 + if (!ev) { 221 + static const char fmt[] = "no event\n"; 222 + bpf_trace_printk(fmt, sizeof(fmt)); 223 + return 0; 224 + } 225 + 226 + struct open_event *oet = bpf_ringbuf_reserve(&rb, sizeof(struct open_event), 0); 227 + if (!oet) 228 + return 0; 229 + 230 + bpf_get_current_comm(oet->e_comm, TASK_COMM_LEN); 231 + static const char fmt[] = "opening %s\n"; 232 + bpf_trace_printk(fmt, sizeof(fmt), ev->e_filename); 233 + 234 + oet->e_ret = 0; // TODO: PT_REGS_RC(ctx); 235 + oet->e_cgid = bpf_get_current_cgroup_id(); 236 + bpf_probe_read_str(&oet->e_filename, sizeof(oet->e_filename), ev->e_filename); 237 + oet->e_flags = ev->e_flags; 238 + oet->e_mode = ev->e_mode; 239 + oet->e_kind = URING_KIND; 240 + oet->e_pid = pid_tgid >> 32; 241 + 242 + bpf_ringbuf_submit(oet, 0); 243 + bpf_map_delete_elem(&tmpmap, &pid_tgid); 244 + return 0; 245 + }
+79 -31
opentrace.ml
··· 12 12 "tracepoint__syscalls__sys_enter_openat2"; 13 13 "tracepoint__syscalls__sys_exit_openat"; 14 14 "tracepoint__syscalls__sys_exit_openat2"; 15 + "trace_io_uring_openat_entry"; 16 + "trace_io_uring_openat_ret"; 15 17 ] 16 18 17 19 let json_to_lexemes json : Jsonm.lexeme list = ··· 29 31 loop [] json |> List.rev 30 32 31 33 module Flags = struct 32 - type t = int 33 - 34 34 include Config 35 - 36 - let mem (v : t) i = Int.equal (i land (v :> int)) (v :> int) 37 35 end 38 36 37 + let print_position ppf lexbuf = 38 + let open Lexing in 39 + let pos = lexbuf.lex_curr_p in 40 + Fmt.pf ppf "%s:%d:%d" pos.pos_fname pos.pos_lnum 41 + (pos.pos_cnum - pos.pos_bol + 1) 42 + 43 + let parse_with_error lexbuf = 44 + try Ok (Parser.filter Lexer.read lexbuf) with 45 + | Lexer.SyntaxError msg -> 46 + Error (Fmt.str "%a: %s\n" print_position lexbuf msg) 47 + | Parser.Error -> Error (Fmt.str "%a: syntax error\n" print_position lexbuf) 48 + 49 + let filter_of_string s = 50 + let lex = Lexing.from_string s in 51 + let filter = parse_with_error lex in 52 + Result.iter (Fmt.pr "filter: %a\n%!" Filter.pp) filter; 53 + filter 54 + 39 55 module Open_event = struct 40 56 open Ctypes 41 57 42 58 type t 43 - type kind = Open_ | Openat | Openat2 59 + type kind = Open_ | Openat | Openat2 | Uring 44 60 45 61 let kind_to_string = function 46 62 | Open_ -> "open" 47 63 | Openat -> "openat" 48 64 | Openat2 -> "openat2" 65 + | Uring -> "Uring" 49 66 50 67 let kind_of_int = function 51 68 | 0 -> Open_ 52 69 | 1 -> Openat 53 70 | 2 -> Openat2 71 + | 3 -> Uring 54 72 | n -> failwith ("Invalid kind of open syscall: " ^ string_of_int n) 55 73 56 74 let t : t structure typ = Ctypes.structure "event" ··· 138 156 bpf_callback 139 157 140 158 let filter_event_by_flag event flags = 141 - flags = [] 142 - || 143 - let fs = Open_event.get_flags event in 144 - List.for_all (fun flag -> Flags.mem flag fs) flags 159 + match flags with 160 + | None -> true 161 + | Some f -> Filter.satisfies f (Open_event.get_flags event) 145 162 146 163 let all poll no_header open_flags = 147 164 if no_header then () else Format.printf "%s" Open_event.csv_header; ··· 153 170 let bpf_callback = ringbuffer_polling_callback ~poll callback (fun _ -> ()) in 154 171 run_ring_buffer bpf_callback 155 172 156 - let exec format output user poll (prog, args) open_flags_filter = 173 + let with_cgroup flag fn = 174 + if not flag then fn None 175 + else 176 + let filename = 177 + Filename.temp_dir ~temp_dir:"/sys/fs/cgroup" "opentrace-" "" 178 + in 179 + Fun.protect 180 + ~finally:(fun () -> Sys.rmdir filename) 181 + (fun () -> fn (Some (Filename.concat filename "cgroup.procs"))) 182 + 183 + let exec format output user poll (prog, args) open_flags_filter cgroups = 157 184 let output = 158 185 match output with 159 186 | Some file -> file ··· 174 201 let mutex = Mutex.create () in 175 202 let pid = Atomic.make None in 176 203 let exit_status = Atomic.make None in 204 + let cgroup = Atomic.make None in 177 205 let _domain = 178 206 Domain.spawn @@ fun () -> 179 - Eio_main.run @@ fun env -> 180 - Mutex.lock mutex; 181 - Condition.wait start_process mutex; 182 - Eio.Switch.run @@ fun sw -> 183 - let p = 184 - Eio.Process.spawn ~sw ~uid (Eio.Stdenv.process_mgr env) (prog :: args) 185 - in 186 - Atomic.set pid (Some (Eio.Process.pid p)); 187 - let status = Eio.Process.await p in 188 - Atomic.set exit_status (Some status) 207 + Eio_posix.run @@ fun env -> 208 + try 209 + Mutex.lock mutex; 210 + Condition.wait start_process mutex; 211 + Eio.Switch.run @@ fun sw -> 212 + with_cgroup cgroups @@ fun group -> 213 + let process = Spawn.make_process group (Some uid) in 214 + let p = Eio.Process.spawn process ~sw (prog :: args) in 215 + Atomic.set pid (Some (Eio.Process.pid p)); 216 + let stat = 217 + Option.map 218 + (fun c -> 219 + Eio.Path.stat ~follow:true Eio.Path.(env#fs / Filename.dirname c)) 220 + group 221 + in 222 + Option.iter (fun v -> Fmt.pr "INO %Ld\n" v.Eio.File.Stat.ino) stat; 223 + Atomic.set cgroup (Option.map (fun v -> v.Eio.File.Stat.ino) stat); 224 + let status = Eio.Process.await p in 225 + Atomic.set exit_status (Some status) 226 + with e -> 227 + Mutex.unlock mutex; 228 + Fmt.epr "Error creating process %s\n" (Printexc.to_string e); 229 + Atomic.set exit_status (Some (`Exited (-1))) 189 230 in 190 231 Out_channel.with_open_bin output @@ fun oc -> 191 232 let encoder = Jsonm.encoder ~minify:false (`Channel oc) in ··· 202 243 | Json -> encode `As 203 244 in 204 245 let callback event = 205 - match Atomic.get pid with 206 - | None -> 0 207 - | Some pid -> 246 + match (Atomic.get cgroup, Atomic.get pid) with 247 + | _, None -> 0 248 + | _, Some pid -> 208 249 (if 209 - Int.equal (Open_event.get_pid event) pid 250 + (if cgroups then 251 + Int64.equal 252 + (Open_event.get_cgid event) 253 + (Option.get (Atomic.get cgroup)) 254 + else Int.equal (Open_event.get_pid event) pid) 210 255 && filter_event_by_flag event open_flags_filter 211 256 then 212 257 match format with ··· 245 290 let no_header = 246 291 let doc = "Disable printing the CSV header" in 247 292 Arg.(value & flag & info [ "no-header" ] ~doc) 293 + 294 + let cgroups = 295 + let doc = "Enable cgroup creation and tracing" in 296 + Arg.(value & flag & info [ "cgroups" ] ~doc) 248 297 249 298 let flag_conv = 250 - let of_string s = 251 - try Ok (Flags.of_string s) with Invalid_argument m -> Error (`Msg m) 252 - in 253 - let pp ppf v = Format.pp_print_string ppf (Flags.to_string v) in 254 - Arg.conv (of_string, pp) 299 + let of_string s = filter_of_string s in 300 + let pp = Filter.pp in 301 + Arg.conv' (of_string, pp) 255 302 256 303 let open_flags_filter = 257 304 let doc = ··· 259 306 Note the filter wants ALL of the flags to be present not just one of \ 260 307 them." 261 308 in 262 - Arg.(value & opt (list flag_conv) [] & info [ "flags" ] ~doc) 309 + Arg.(value & opt (some flag_conv) None & info [ "flags" ] ~doc) 263 310 264 311 let user = 265 312 let doc = "Username or UID to execute program as" in ··· 323 370 and+ output = output 324 371 and+ args = Arg.(value & pos_right 0 string [] & Arg.info [] ~docv:"ARGS") 325 372 and+ open_flags_filter = open_flags_filter 373 + and+ cgroups = cgroups 326 374 and+ poll = polling in 327 - exec format output user poll (prog, args) open_flags_filter 375 + exec format output user poll (prog, args) open_flags_filter cgroups 328 376 329 377 let opentrace_cmd = 330 378 let doc = "Trace all open system calls" in
+56
opentrace_stubs.c
··· 1 + #include <stdlib.h> 2 + #include <unistd.h> 3 + #include <fcntl.h> 4 + #include <string.h> 5 + #include <errno.h> 6 + 7 + #include <caml/mlvalues.h> 8 + #include <caml/unixsupport.h> 9 + #include <caml/memory.h> 10 + #include <caml/custom.h> 11 + #include <caml/fail.h> 12 + 13 + #include "include/fork_action.h" 14 + 15 + static void action_setuid(int errors, value v_config) { 16 + #ifdef _WIN32 17 + eio_unix_fork_error(errors, "action_setuid", "Unsupported operation on windows"); 18 + #else 19 + value v_uid = Field(v_config, 1); 20 + int r; 21 + r = setuid(Int_val(v_uid)); 22 + if (r != 0) { 23 + eio_unix_fork_error(errors, "setuid", strerror(errno)); 24 + _exit(1); 25 + } 26 + #endif 27 + } 28 + 29 + CAMLprim value eio_unix_fork_setuid(value v_unit) { 30 + return Val_fork_fn(action_setuid); 31 + } 32 + 33 + static void action_setcgroup(int errors, value v_config) { 34 + value v_path = Field(v_config, 1); 35 + 36 + int r; 37 + pid_t pid = getpid(); 38 + FILE *f = fopen(String_val(v_path), "w"); 39 + if (f == NULL) { 40 + eio_unix_fork_error(errors, "cgroup", strerror(errno)); 41 + _exit(1); 42 + } 43 + 44 + if (fprintf(f, "%d\n", pid) < 0) { 45 + fclose(f); 46 + eio_unix_fork_error(errors, "cgroup", strerror(errno)); 47 + _exit(1); 48 + } 49 + 50 + fclose(f); 51 + } 52 + 53 + CAMLprim value eio_unix_fork_setcgroup(value v_unit) { 54 + return Val_fork_fn(action_setcgroup); 55 + } 56 +
+21
parser.mly
··· 1 + %token <string> FLAG 2 + %token LPAREN RPAREN 3 + %token OR AND 4 + %token NOT 5 + %token EOF 6 + %left OR 7 + %left AND 8 + %nonassoc NOT 9 + 10 + %start <Filter.t> filter 11 + %% 12 + 13 + filter: 14 + | f = expr; EOF { f } 15 + 16 + expr: 17 + | f = FLAG { Filter.Flag (Config.of_string f) } 18 + | LPAREN; e = expr; RPAREN { e } 19 + | e1 = expr; AND; e2 = expr { Filter.And (e1, e2) } 20 + | e1 = expr; OR; e2 = expr { Filter.Or (e1, e2) } 21 + | NOT; e = expr { Filter.Not e }
+88
spawn.ml
··· 1 + open Eio_posix 2 + open Eio.Std 3 + 4 + type (_, _, _) Eio.Resource.pi += 5 + | Posix_dir : ('t, 't -> Low_level.dir_fd, [> `Posix_dir ]) Eio.Resource.pi 6 + 7 + let as_posix_dir (Eio.Resource.T (t, ops)) = 8 + match Eio.Resource.get_opt ops Posix_dir with 9 + | None -> None 10 + | Some fn -> Some (fn t) 11 + 12 + module Process_impl = struct 13 + type t = Low_level.Process.t 14 + type tag = [ `Generic | `Unix ] 15 + 16 + let pid = Low_level.Process.pid 17 + 18 + let await t = 19 + match Eio.Promise.await @@ Low_level.Process.exit_status t with 20 + | Unix.WEXITED i -> `Exited i 21 + | Unix.WSIGNALED i -> `Signaled i 22 + | Unix.WSTOPPED _ -> assert false 23 + 24 + let signal = Low_level.Process.signal 25 + end 26 + 27 + let process = 28 + let handler = Eio.Process.Pi.process (module Process_impl) in 29 + fun proc -> Eio.Resource.T (proc, handler) 30 + 31 + module T = struct 32 + type t = unit 33 + 34 + external action_setuid : unit -> Eio_unix.Private.Fork_action.fork_fn 35 + = "eio_unix_fork_setuid" 36 + 37 + let action_setuid = action_setuid () 38 + 39 + let setuid (uid : int) = 40 + Eio_unix.Private.Fork_action. 41 + { run = (fun k -> k (Obj.repr (action_setuid, uid))) } 42 + 43 + external action_setcgroup : unit -> Eio_unix.Private.Fork_action.fork_fn 44 + = "eio_unix_fork_setcgroup" 45 + 46 + let action_setcgroup = action_setcgroup () 47 + 48 + let setcgroup group = 49 + Eio_unix.Private.Fork_action. 50 + { run = (fun k -> k (Obj.repr (action_setcgroup, group))) } 51 + 52 + let spawn_unix () ~group ~uid ~sw ?cwd ~env ~fds ~executable args = 53 + let actions = 54 + Low_level.Process.Fork_action. 55 + [ inherit_fds fds; execve executable ~argv:(Array.of_list args) ~env ] 56 + in 57 + let actions = 58 + match uid with None -> actions | Some uid -> setuid uid :: actions 59 + in 60 + let actions = 61 + match group with None -> actions | Some g -> setcgroup g :: actions 62 + in 63 + let with_actions cwd fn = 64 + match cwd with 65 + | None -> fn actions 66 + | Some ((dir, path) : Eio.Fs.dir_ty Eio.Path.t) -> ( 67 + match as_posix_dir dir with 68 + | None -> Fmt.invalid_arg "cwd is not an OS directory!" 69 + | Some dirfd -> 70 + Switch.run ~name:"spawn_unix" @@ fun launch_sw -> 71 + let cwd = 72 + Low_level.openat ~sw:launch_sw ~mode:0 dirfd path 73 + Low_level.Open_flags.(rdonly + directory) 74 + in 75 + fn (Low_level.Process.Fork_action.fchdir cwd :: actions)) 76 + in 77 + with_actions cwd @@ fun actions -> 78 + process (Low_level.Process.spawn ~sw actions) 79 + end 80 + 81 + let make_process group uid = 82 + let module T = struct 83 + type t = unit 84 + 85 + let spawn_unix = T.spawn_unix ~group ~uid 86 + end in 87 + let h = Eio_unix.Process.Pi.mgr_unix (module Eio_unix.Process.Make_mgr (T)) in 88 + Eio.Resource.T ((), h)
+280
uring.h
··· 1 + #ifndef __URING_IO_H 2 + #define __URING_IO_H 3 + 4 + #include <stdbool.h> 5 + #define TASK_COMM_LEN 16 6 + #define MAX_OP_STR_LEN 127 7 + 8 + enum tracepoint_t { 9 + IO_URING_CREATE, 10 + IO_URING_REGISTER, 11 + IO_URING_FILE_GET, 12 + IO_URING_SUBMIT_SQE, 13 + IO_URING_QUEUE_ASYNC_WORK, 14 + IO_URING_POLL_ARM, 15 + IO_URING_TASK_ADD, 16 + IO_URING_TASK_WORK_RUN, 17 + IO_URING_SHORT_WRITE, 18 + IO_URING_LOCAL_WORK_RUN, 19 + IO_URING_DEFER, 20 + IO_URING_LINK, 21 + IO_URING_FAIL_LINK, 22 + IO_URING_CQRING_WAIT, 23 + IO_URING_REQ_FAILED, 24 + IO_URING_CQE_OVERFLOW, 25 + IO_URING_COMPLETE, 26 + KPROBE_IO_INIT_NEW_WORKER, 27 + SYS_ENTER_IO_URING_SETUP, 28 + SYS_EXIT_IO_URING_SETUP, 29 + SYS_ENTER_IO_URING_REGISTER, 30 + SYS_EXIT_IO_URING_REGISTER, 31 + SYS_ENTER_IO_URING_ENTER, 32 + SYS_EXIT_IO_URING_ENTER 33 + }; 34 + 35 + struct io_uring_create { 36 + int fd; 37 + void *ctx; 38 + unsigned long sq_entries; 39 + unsigned long cq_entries; 40 + unsigned long flags; 41 + }; 42 + 43 + struct io_uring_register { 44 + void *ctx; 45 + unsigned opcode; 46 + unsigned nr_files; 47 + unsigned nr_bufs; 48 + long ret; 49 + }; 50 + 51 + struct io_uring_file_get { 52 + void *ctx; 53 + void *req; 54 + /* unsigned long long user_data; */ 55 + int fd; 56 + }; 57 + 58 + struct io_uring_submit_sqe { 59 + void *ctx; 60 + void *req; 61 + /* unsigned long long user_data; */ 62 + unsigned char opcode; 63 + unsigned long flags; 64 + bool force_nonblock; 65 + bool sq_thread; 66 + /* unsigned long __data_loc_op_str; */ 67 + char op_str[MAX_OP_STR_LEN]; 68 + }; 69 + 70 + struct io_uring_queue_async_work { 71 + void *ctx; 72 + void *req; 73 + /* unsigned long long user_data; */ 74 + unsigned char opcode; 75 + unsigned int flags; 76 + void *work; 77 + /* int rw; */ 78 + /* unsigned long __data_loc_op_str; */ 79 + char op_str[MAX_OP_STR_LEN]; 80 + }; 81 + 82 + struct io_uring_poll_arm { 83 + void *ctx; 84 + void *req; 85 + /* unsigned long long user_data; */ 86 + unsigned char opcode; 87 + int mask; 88 + int events; 89 + char op_str[MAX_OP_STR_LEN]; 90 + }; 91 + 92 + struct io_uring_task_add { 93 + void *ctx; 94 + void *req; 95 + /* unsigned long long user_data; */ 96 + unsigned char opcode; 97 + int mask; 98 + char op_str[MAX_OP_STR_LEN]; 99 + }; 100 + 101 + struct io_uring_task_work_run { 102 + void *tctx; 103 + unsigned int count; 104 + unsigned int loops; 105 + }; 106 + 107 + struct io_uring_short_write { 108 + void *ctx; 109 + unsigned long long fpos; 110 + unsigned long long wanted; 111 + unsigned long long got; 112 + }; 113 + 114 + struct io_uring_local_work_run { 115 + void *ctx; 116 + int count; 117 + unsigned int loops; 118 + }; 119 + 120 + struct io_uring_defer { 121 + void *ctx; 122 + void *req; 123 + /* unsigned long long data; */ 124 + unsigned char opcode; 125 + char op_str[MAX_OP_STR_LEN]; 126 + }; 127 + 128 + struct io_uring_link { 129 + 130 + void *ctx; 131 + void *req; 132 + void *target_req; 133 + }; 134 + 135 + struct io_uring_fail_link { 136 + void *ctx; 137 + void *req; 138 + /* unsigned long long user_data; */ 139 + unsigned char opcode; 140 + void *link; 141 + char op_str[MAX_OP_STR_LEN]; 142 + }; 143 + 144 + struct io_uring_cqring_wait { 145 + void *ctx; 146 + int min_events; 147 + }; 148 + 149 + struct io_uring_req_failed { 150 + void *ctx; 151 + void *req; 152 + /* unsigned long long user_data; */ 153 + unsigned char opcode; 154 + unsigned char flags; 155 + unsigned char ioprio; 156 + unsigned long long off; 157 + unsigned long long addr; 158 + unsigned long len; 159 + unsigned long op_flags; 160 + unsigned int buf_index; 161 + unsigned int personality; 162 + unsigned long file_index; 163 + unsigned long long pad1; 164 + unsigned long long addr3; 165 + int error; 166 + char op_str[MAX_OP_STR_LEN]; 167 + }; 168 + 169 + struct io_uring_cqe_overflow { 170 + void *ctx; 171 + unsigned long long user_data; 172 + long res; 173 + unsigned long cflags; 174 + void *ocqe; 175 + }; 176 + 177 + struct io_uring_complete { 178 + void *ctx; 179 + void *req; 180 + /* unsigned long long user_data; */ 181 + int res; 182 + unsigned int cflags; 183 + /* unsigned long long extra1; */ 184 + /* unsigned long long extra2; */ 185 + }; 186 + 187 + struct io_init_new_worker { 188 + int io_worker_tid; 189 + }; 190 + 191 + /* struct sys_enter_io_uring_enter { */ 192 + /* unsigned int fd; */ 193 + /* unsigned long to_submit; */ 194 + /* unsigned long min_complete; */ 195 + /* unsigned long flags; */ 196 + /* unsigned */ 197 + /* } */ 198 + 199 + struct event { 200 + enum tracepoint_t ty; 201 + int pid; 202 + int tid; 203 + unsigned long long ts; 204 + char comm[TASK_COMM_LEN]; 205 + union { 206 + struct io_uring_create io_uring_create; 207 + struct io_uring_register io_uring_register; 208 + struct io_uring_file_get io_uring_file_get; 209 + struct io_uring_submit_sqe io_uring_submit_sqe; 210 + struct io_uring_queue_async_work io_uring_queue_async_work; 211 + struct io_uring_poll_arm io_uring_poll_arm; 212 + struct io_uring_task_add io_uring_task_add; 213 + struct io_uring_task_work_run io_uring_task_work_run; 214 + struct io_uring_short_write io_uring_short_write; 215 + struct io_uring_local_work_run io_uring_local_work_run; 216 + struct io_uring_defer io_uring_defer; 217 + struct io_uring_link io_uring_link; 218 + struct io_uring_fail_link io_uring_fail_link; 219 + struct io_uring_cqring_wait io_uring_cqring_wait; 220 + struct io_uring_req_failed io_uring_req_failed; 221 + struct io_uring_cqe_overflow io_uring_cqe_overflow; 222 + struct io_uring_complete io_uring_complete; 223 + struct io_init_new_worker io_init_new_worker; 224 + }; 225 + }; 226 + 227 + /* enum io_uring_op { */ 228 + /* IORING_OP_NOP = 0, */ 229 + /* IORING_OP_READV = 1, */ 230 + /* IORING_OP_WRITEV = 2, */ 231 + /* IORING_OP_FSYNC = 3, */ 232 + /* IORING_OP_READ_FIXED = 4, */ 233 + /* IORING_OP_WRITE_FIXED = 5, */ 234 + /* IORING_OP_POLL_ADD = 6, */ 235 + /* IORING_OP_POLL_REMOVE = 7, */ 236 + /* IORING_OP_SYNC_FILE_RANGE = 8, */ 237 + /* IORING_OP_SENDMSG = 9, */ 238 + /* IORING_OP_RECVMSG = 10, */ 239 + /* IORING_OP_TIMEOUT = 11, */ 240 + /* IORING_OP_TIMEOUT_REMOVE = 12, */ 241 + /* IORING_OP_ACCEPT = 13, */ 242 + /* IORING_OP_ASYNC_CANCEL = 14, */ 243 + /* IORING_OP_LINK_TIMEOUT = 15, */ 244 + /* IORING_OP_CONNECT = 16, */ 245 + /* IORING_OP_FALLOCATE = 17, */ 246 + /* IORING_OP_OPENAT = 18, */ 247 + /* IORING_OP_CLOSE = 19, */ 248 + /* IORING_OP_FILES_UPDATE = 20, */ 249 + /* IORING_OP_STATX = 21, */ 250 + /* IORING_OP_READ = 22, */ 251 + /* IORING_OP_WRITE = 23, */ 252 + /* IORING_OP_FADVISE = 24, */ 253 + /* IORING_OP_MADVISE = 25, */ 254 + /* IORING_OP_SEND = 26, */ 255 + /* IORING_OP_RECV = 27, */ 256 + /* IORING_OP_OPENAT2 = 28, */ 257 + /* IORING_OP_EPOLL_CTL = 29, */ 258 + /* IORING_OP_SPLICE = 30, */ 259 + /* IORING_OP_PROVIDE_BUFFERS = 31, */ 260 + /* IORING_OP_REMOVE_BUFFERS = 32, */ 261 + /* IORING_OP_TEE = 33, */ 262 + /* IORING_OP_SHUTDOWN = 34, */ 263 + /* IORING_OP_RENAMEAT = 35, */ 264 + /* IORING_OP_UNLINKAT = 36, */ 265 + /* IORING_OP_MKDIRAT = 37, */ 266 + /* IORING_OP_SYMLINKAT = 38, */ 267 + /* IORING_OP_LINKAT = 39, */ 268 + /* IORING_OP_MSG_RING = 40, */ 269 + /* IORING_OP_FSETXATTR = 41, */ 270 + /* IORING_OP_SETXATTR = 42, */ 271 + /* IORING_OP_FGETXATTR = 43, */ 272 + /* IORING_OP_GETXATTR = 44, */ 273 + /* IORING_OP_SOCKET = 45, */ 274 + /* IORING_OP_URING_CMD = 46, */ 275 + /* IORING_OP_SEND_ZC = 47, */ 276 + /* IORING_OP_SENDMSG_ZC = 48, */ 277 + /* IORING_OP_LAST = 49, */ 278 + /* }; */ 279 + 280 + #endif