disksnoop.php 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <?php
  2. define("REQ_WRITE", 1); // from include/linux/blk_types.h
  3. $prog = <<<EOT
  4. #include <uapi/linux/ptrace.h>
  5. #include <linux/blk-mq.h>
  6. BPF_HASH(start, struct request *);
  7. void trace_start(struct pt_regs *ctx, struct request *req) {
  8. u64 ts = bpf_ktime_get_ns();
  9. start.update(&req, &ts);
  10. }
  11. void trace_completion(struct pt_regs *ctx, struct request *req) {
  12. u64 *tsp, delta;
  13. tsp = start.lookup(&req);
  14. if (tsp != 0) {
  15. delta = bpf_ktime_get_ns() - *tsp;
  16. bpf_trace_printk("%d %x %d\\n", req->__data_len,
  17. req->cmd_flags, delta / 1000);
  18. start.delete(&req);
  19. }
  20. }
  21. EOT;
  22. $b = new Bpf(["text" => $prog]);
  23. // attach trace_start
  24. if ($b->get_kprobe_functions("blk_start_request")) {
  25. $b->attach_kprobe("blk_start_request", "trace_start");
  26. }
  27. $b->attach_kprobe("blk_mq_start_request", "trace_start");
  28. // attach trace_completion
  29. if ($b->get_kprobe_functions("__blk_account_io_done")) {
  30. $b->attach_kprobe("__blk_account_io_done", "trace_completion");
  31. } elseif ($b->get_kprobe_functions("blk_account_io_done")) {
  32. $b->attach_kprobe("blk_account_io_done", "trace_completion");
  33. } else {
  34. $b->attach_kprobe("blk_mq_end_request", "trace_completion");
  35. }
  36. printf("%-18s %-2s %-7s %8s\n", "TIME(s)", "T", "BYTES", "LAT(ms)");
  37. $start = 0;
  38. while (true) {
  39. $fields = $b->trace_fields();
  40. list($task, $pid, $cpu, $flags, $ts, $msg) = $fields;
  41. $parts = preg_split('/\s+/', $msg);
  42. if (count($parts) < 3) continue;
  43. list($bytes_s, $bflags_s, $us_s) = $parts;
  44. $bflags = intval($bflags_s, 16);
  45. if ($bflags & REQ_WRITE) {
  46. $type_s = "W";
  47. } else {
  48. $type_s = "R";
  49. }
  50. $ms = intval($us_s) / 1000.0;
  51. printf("%-18.9f %-2s %-7s %8.2f\n", $ts, $type_s, $bytes_s, $ms);
  52. }