rbbcc 0.11.5 → 0.11.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/rbbcc/consts.rb +5 -1
- data/lib/rbbcc/table.rb +35 -3
- data/lib/rbbcc/version.rb +1 -1
- data/rbbcc.gemspec +5 -2
- metadata +2 -60
- data/docs/README.md +0 -7
- data/docs/answers/01-hello-world.rb +0 -16
- data/docs/answers/02-sys_sync.rb +0 -18
- data/docs/answers/03-hello_fields.rb +0 -33
- data/docs/answers/04-sync_timing.rb +0 -46
- data/docs/answers/05-sync_count.rb +0 -54
- data/docs/answers/06-disksnoop.rb +0 -71
- data/docs/answers/07-hello_perf_output.rb +0 -59
- data/docs/answers/08-sync_perf_output.rb +0 -60
- data/docs/answers/09-bitehist.rb +0 -32
- data/docs/answers/10-disklatency.rb +0 -51
- data/docs/answers/11-vfsreadlat.c +0 -46
- data/docs/answers/11-vfsreadlat.rb +0 -66
- data/docs/answers/12-urandomread.rb +0 -38
- data/docs/answers/13-disksnoop_fixed.rb +0 -108
- data/docs/answers/14-strlen_count.rb +0 -46
- data/docs/answers/15-nodejs_http_server.rb +0 -44
- data/docs/answers/16-task_switch.c +0 -23
- data/docs/answers/16-task_switch.rb +0 -17
- data/docs/answers/node-server.js +0 -11
- data/docs/getting_started.md +0 -154
- data/docs/projects_using_rbbcc.md +0 -43
- data/docs/tutorial_bcc_ruby_developer.md +0 -774
- data/docs/tutorial_bcc_ruby_developer_japanese.md +0 -770
- data/examples/bitehist.rb +0 -46
- data/examples/charty/Gemfile +0 -11
- data/examples/charty/Gemfile.lock +0 -48
- data/examples/charty/bitehist-unicode.rb +0 -87
- data/examples/collectsyscall.rb +0 -182
- data/examples/dddos.rb +0 -112
- data/examples/disksnoop.rb +0 -73
- data/examples/dns_blocker.rb +0 -134
- data/examples/example.gif +0 -0
- data/examples/extract_arg.rb +0 -26
- data/examples/hello_fields.rb +0 -32
- data/examples/hello_perf_output.rb +0 -64
- data/examples/hello_ring_buffer.rb +0 -64
- data/examples/hello_world.rb +0 -6
- data/examples/kvm_hypercall.rb +0 -69
- data/examples/lsm_sockblock.rb +0 -141
- data/examples/mallocstack.rb +0 -63
- data/examples/networking/http_filter/http-parse-simple.c +0 -114
- data/examples/networking/http_filter/http-parse-simple.rb +0 -85
- data/examples/pin_maps_a.rb +0 -88
- data/examples/pin_maps_b.rb +0 -71
- data/examples/py-orig/sockblock.py +0 -119
- data/examples/ruby_usdt.rb +0 -105
- data/examples/sbrk_trace.rb +0 -204
- data/examples/ssl_http_trace.rb +0 -274
- data/examples/syscalluname.rb +0 -39
- data/examples/table.rb +0 -15
- data/examples/tools/bashreadline.rb +0 -83
- data/examples/tools/execsnoop.rb +0 -229
- data/examples/tools/runqlat.rb +0 -148
- data/examples/urandomread-explicit.rb +0 -58
- data/examples/urandomread.rb +0 -39
- data/examples/usdt-test.rb +0 -6
- data/examples/usdt.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59d0fb02bff1acabccf1f231bd3642bfa3da9ef1fc796c580d8c1d9c4c5098bc
|
|
4
|
+
data.tar.gz: 5e033fa5c3957b1d7e822eec06c4bff9f1158046a292897f61401206d56fff9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ca57cd8e17b0035c4e670e0a3fc18ee53544cd14b81a5cdf62b91a504b848b59b3ad1f38658ae68fff0c1cc33126f36ea708b73b5378a2d83223651ce0a5441d
|
|
7
|
+
data.tar.gz: d37158b96887c9500ee791209d44bc03902efda99466623eccff0d1de83c18dc6fca174beb37c50a4d36d0caa84f3dbf2b6e1aee21470a47e9cc2af7ce2fbc10
|
data/Gemfile.lock
CHANGED
data/lib/rbbcc/consts.rb
CHANGED
data/lib/rbbcc/table.rb
CHANGED
|
@@ -40,6 +40,8 @@ module RbBCC
|
|
|
40
40
|
fields << [field_type, field_name].join(" ")
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
+
return nil if fields.empty?
|
|
44
|
+
|
|
43
45
|
klass = Fiddle::Importer.struct(fields)
|
|
44
46
|
char_ps = fields.select {|f| f =~ /^char\[(\d+)\] ([_a-zA-Z0-9]+)/ }
|
|
45
47
|
unless char_ps.empty?
|
|
@@ -280,6 +282,11 @@ module RbBCC
|
|
|
280
282
|
false # TODO: implement me in the future
|
|
281
283
|
end
|
|
282
284
|
|
|
285
|
+
# Just a wrapper to BCC class method
|
|
286
|
+
def pin!(path)
|
|
287
|
+
BCC.pin!(self.map_fd, path)
|
|
288
|
+
end
|
|
289
|
+
|
|
283
290
|
private
|
|
284
291
|
def normalize_key(key)
|
|
285
292
|
case key
|
|
@@ -368,7 +375,7 @@ module RbBCC
|
|
|
368
375
|
end
|
|
369
376
|
|
|
370
377
|
def event(data)
|
|
371
|
-
@event_class ||= get_event_class
|
|
378
|
+
@event_class ||= (get_event_class || self.leaftype)
|
|
372
379
|
ev = @event_class.malloc
|
|
373
380
|
Fiddle::Pointer.new(ev.to_ptr)[0, @event_class.size] = data[0, @event_class.size]
|
|
374
381
|
return ev
|
|
@@ -429,7 +436,28 @@ module RbBCC
|
|
|
429
436
|
|
|
430
437
|
class RingBuf < TableBase
|
|
431
438
|
include EventTypeSupported
|
|
432
|
-
|
|
439
|
+
|
|
440
|
+
# Make a dynamic BCC program to load the pinned ringbuf map
|
|
441
|
+
def self.from_pin(path, leaftype, size, name: "events")
|
|
442
|
+
map_fd = Clib.bpf_obj_get(path)
|
|
443
|
+
if map_fd < 0
|
|
444
|
+
raise SystemCallError.new("Could not open pinned map", Fiddle.last_error)
|
|
445
|
+
end
|
|
446
|
+
leaftype_typename = case leaftype
|
|
447
|
+
when /\Astruct\s+(\w+)\s+{/m
|
|
448
|
+
"struct #{Regexp.last_match(1)}"
|
|
449
|
+
else
|
|
450
|
+
leaftype
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
prog = <<~CLANG
|
|
454
|
+
#{leaftype}
|
|
455
|
+
BPF_TABLE_PINNED("ringbuf", u32, #{leaftype_typename}, #{name}, #{size}, "#{path}");
|
|
456
|
+
CLANG
|
|
457
|
+
b = BCC.new(text: prog)
|
|
458
|
+
b[name.to_s]
|
|
459
|
+
end
|
|
460
|
+
|
|
433
461
|
def initialize(bpf, map_id, map_fd, keytype, leaftype, name: nil)
|
|
434
462
|
super
|
|
435
463
|
@_ringbuf = nil
|
|
@@ -438,7 +466,7 @@ module RbBCC
|
|
|
438
466
|
end
|
|
439
467
|
|
|
440
468
|
def event(data)
|
|
441
|
-
@event_class ||= get_event_class
|
|
469
|
+
@event_class ||= (get_event_class || self.leaftype)
|
|
442
470
|
ev = @event_class.malloc
|
|
443
471
|
Fiddle::Pointer.new(ev.to_ptr)[0, @event_class.size] = data[0, @event_class.size]
|
|
444
472
|
return ev
|
|
@@ -470,6 +498,10 @@ module RbBCC
|
|
|
470
498
|
@bpf._open_ring_buffer(@map_fd, fn, ctx)
|
|
471
499
|
nil
|
|
472
500
|
end
|
|
501
|
+
|
|
502
|
+
def ring_buffer_poll(timeout=-1)
|
|
503
|
+
@bpf.ring_buffer_poll(timeout)
|
|
504
|
+
end
|
|
473
505
|
end
|
|
474
506
|
|
|
475
507
|
class StackTrace < TableBase
|
data/lib/rbbcc/version.rb
CHANGED
data/rbbcc.gemspec
CHANGED
|
@@ -15,9 +15,12 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
|
|
16
16
|
# Specify which files should be added to the gem when it is released.
|
|
17
17
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
18
|
-
spec.files
|
|
19
|
-
`git ls-files -z`.split("\x0").reject
|
|
18
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
19
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
20
|
+
f.match(%r{^(test|spec|features|docs|examples)/}) || f.match(/\.(gif|jpe?g|png)\Z/)
|
|
21
|
+
end
|
|
20
22
|
end
|
|
23
|
+
|
|
21
24
|
spec.bindir = "exe"
|
|
22
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
23
26
|
spec.require_paths = ["lib"]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rbbcc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.11.
|
|
4
|
+
version: 0.11.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Uchio Kondo
|
|
@@ -53,64 +53,6 @@ files:
|
|
|
53
53
|
- ci/Dockerfile.0.17.0-2.7.2
|
|
54
54
|
- ci/Dockerfile.0.17.0-3.0.0
|
|
55
55
|
- ci/Dockerfile.ci_base
|
|
56
|
-
- docs/README.md
|
|
57
|
-
- docs/answers/01-hello-world.rb
|
|
58
|
-
- docs/answers/02-sys_sync.rb
|
|
59
|
-
- docs/answers/03-hello_fields.rb
|
|
60
|
-
- docs/answers/04-sync_timing.rb
|
|
61
|
-
- docs/answers/05-sync_count.rb
|
|
62
|
-
- docs/answers/06-disksnoop.rb
|
|
63
|
-
- docs/answers/07-hello_perf_output.rb
|
|
64
|
-
- docs/answers/08-sync_perf_output.rb
|
|
65
|
-
- docs/answers/09-bitehist.rb
|
|
66
|
-
- docs/answers/10-disklatency.rb
|
|
67
|
-
- docs/answers/11-vfsreadlat.c
|
|
68
|
-
- docs/answers/11-vfsreadlat.rb
|
|
69
|
-
- docs/answers/12-urandomread.rb
|
|
70
|
-
- docs/answers/13-disksnoop_fixed.rb
|
|
71
|
-
- docs/answers/14-strlen_count.rb
|
|
72
|
-
- docs/answers/15-nodejs_http_server.rb
|
|
73
|
-
- docs/answers/16-task_switch.c
|
|
74
|
-
- docs/answers/16-task_switch.rb
|
|
75
|
-
- docs/answers/node-server.js
|
|
76
|
-
- docs/getting_started.md
|
|
77
|
-
- docs/projects_using_rbbcc.md
|
|
78
|
-
- docs/tutorial_bcc_ruby_developer.md
|
|
79
|
-
- docs/tutorial_bcc_ruby_developer_japanese.md
|
|
80
|
-
- examples/bitehist.rb
|
|
81
|
-
- examples/charty/Gemfile
|
|
82
|
-
- examples/charty/Gemfile.lock
|
|
83
|
-
- examples/charty/bitehist-unicode.rb
|
|
84
|
-
- examples/collectsyscall.rb
|
|
85
|
-
- examples/dddos.rb
|
|
86
|
-
- examples/disksnoop.rb
|
|
87
|
-
- examples/dns_blocker.rb
|
|
88
|
-
- examples/example.gif
|
|
89
|
-
- examples/extract_arg.rb
|
|
90
|
-
- examples/hello_fields.rb
|
|
91
|
-
- examples/hello_perf_output.rb
|
|
92
|
-
- examples/hello_ring_buffer.rb
|
|
93
|
-
- examples/hello_world.rb
|
|
94
|
-
- examples/kvm_hypercall.rb
|
|
95
|
-
- examples/lsm_sockblock.rb
|
|
96
|
-
- examples/mallocstack.rb
|
|
97
|
-
- examples/networking/http_filter/http-parse-simple.c
|
|
98
|
-
- examples/networking/http_filter/http-parse-simple.rb
|
|
99
|
-
- examples/pin_maps_a.rb
|
|
100
|
-
- examples/pin_maps_b.rb
|
|
101
|
-
- examples/py-orig/sockblock.py
|
|
102
|
-
- examples/ruby_usdt.rb
|
|
103
|
-
- examples/sbrk_trace.rb
|
|
104
|
-
- examples/ssl_http_trace.rb
|
|
105
|
-
- examples/syscalluname.rb
|
|
106
|
-
- examples/table.rb
|
|
107
|
-
- examples/tools/bashreadline.rb
|
|
108
|
-
- examples/tools/execsnoop.rb
|
|
109
|
-
- examples/tools/runqlat.rb
|
|
110
|
-
- examples/urandomread-explicit.rb
|
|
111
|
-
- examples/urandomread.rb
|
|
112
|
-
- examples/usdt-test.rb
|
|
113
|
-
- examples/usdt.rb
|
|
114
56
|
- exe/rbbcc
|
|
115
57
|
- lib/rbbcc.rb
|
|
116
58
|
- lib/rbbcc/bcc.rb
|
|
@@ -147,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
147
89
|
- !ruby/object:Gem::Version
|
|
148
90
|
version: '0'
|
|
149
91
|
requirements: []
|
|
150
|
-
rubygems_version: 4.0.
|
|
92
|
+
rubygems_version: 4.0.10
|
|
151
93
|
specification_version: 4
|
|
152
94
|
summary: BCC port for MRI
|
|
153
95
|
test_files: []
|
data/docs/README.md
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# RbBCC Docs
|
|
2
|
-
|
|
3
|
-
* [Getting Started](getting_started.md)
|
|
4
|
-
* [Ruby Tutorial](tutorial_bcc_ruby_developer.md)
|
|
5
|
-
* [Projects Using RbBCC](projects_using_rbbcc.md)
|
|
6
|
-
|
|
7
|
-
**Please see also [BCC itself's README](https://github.com/iovisor/bcc/#readme) and [docs](https://github.com/iovisor/bcc/tree/master/docs).**
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Original hello_world.py:
|
|
3
|
-
# Copyright (c) PLUMgrid, Inc.
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
5
|
-
#
|
|
6
|
-
# This Ruby version follows the Apache License 2.0
|
|
7
|
-
|
|
8
|
-
# run in project examples directory with:
|
|
9
|
-
# sudo ./hello_world.rb"
|
|
10
|
-
# see trace_fields.rb for a longer example
|
|
11
|
-
|
|
12
|
-
require "rbbcc"
|
|
13
|
-
include RbBCC
|
|
14
|
-
|
|
15
|
-
# This may not work for 4.17 on x64, you need replace kprobe__sys_clone with kprobe____x64_sys_clone
|
|
16
|
-
BCC.new(text: 'int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print
|
data/docs/answers/02-sys_sync.rb
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
3
|
-
|
|
4
|
-
require "rbbcc"
|
|
5
|
-
include RbBCC
|
|
6
|
-
|
|
7
|
-
puts "Tracing sys_sync()... Ctrl-C to end."
|
|
8
|
-
begin
|
|
9
|
-
BCC.new(text: <<~BPF).trace_print
|
|
10
|
-
int kprobe__sys_sync(void *ctx) {
|
|
11
|
-
bpf_trace_printk("sys_sync() called\\n");
|
|
12
|
-
return 0;
|
|
13
|
-
}
|
|
14
|
-
BPF
|
|
15
|
-
rescue Interrupt
|
|
16
|
-
puts
|
|
17
|
-
puts "Done"
|
|
18
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
3
|
-
|
|
4
|
-
require "rbbcc"
|
|
5
|
-
include RbBCC
|
|
6
|
-
|
|
7
|
-
# define BPF program
|
|
8
|
-
prog = <<BPF
|
|
9
|
-
int hello(void *ctx) {
|
|
10
|
-
bpf_trace_printk("Hello, World!\\n");
|
|
11
|
-
return 0;
|
|
12
|
-
}
|
|
13
|
-
BPF
|
|
14
|
-
|
|
15
|
-
# load BPF program
|
|
16
|
-
b = BCC.new(text: prog)
|
|
17
|
-
b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
|
|
18
|
-
|
|
19
|
-
# header
|
|
20
|
-
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
|
|
21
|
-
|
|
22
|
-
# format output
|
|
23
|
-
begin
|
|
24
|
-
b.trace_fields do |task, pid, cpu, flags, ts, msg|
|
|
25
|
-
print("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
|
|
26
|
-
end
|
|
27
|
-
rescue Interrupt
|
|
28
|
-
puts
|
|
29
|
-
puts "Done"
|
|
30
|
-
rescue => e
|
|
31
|
-
p e
|
|
32
|
-
retry
|
|
33
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Original sync_timing.py:
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
5
|
-
# This Ruby version follows the Apache License 2.0
|
|
6
|
-
|
|
7
|
-
require "rbbcc"
|
|
8
|
-
include RbBCC
|
|
9
|
-
|
|
10
|
-
# load BPF program
|
|
11
|
-
b = BCC.new(text: <<BPF)
|
|
12
|
-
#include <uapi/linux/ptrace.h>
|
|
13
|
-
|
|
14
|
-
BPF_HASH(last);
|
|
15
|
-
|
|
16
|
-
int do_trace(struct pt_regs *ctx) {
|
|
17
|
-
u64 ts, *tsp, delta, key = 0;
|
|
18
|
-
|
|
19
|
-
// attempt to read stored timestamp
|
|
20
|
-
tsp = last.lookup(&key);
|
|
21
|
-
if (tsp != 0) {
|
|
22
|
-
delta = bpf_ktime_get_ns() - *tsp;
|
|
23
|
-
if (delta < 1000000000) {
|
|
24
|
-
// output if time is less than 1 second
|
|
25
|
-
bpf_trace_printk("%d\\n", delta / 1000000);
|
|
26
|
-
}
|
|
27
|
-
last.delete(&key);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// update stored timestamp
|
|
31
|
-
ts = bpf_ktime_get_ns();
|
|
32
|
-
last.update(&key, &ts);
|
|
33
|
-
return 0;
|
|
34
|
-
}
|
|
35
|
-
BPF
|
|
36
|
-
|
|
37
|
-
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
|
38
|
-
puts("Tracing for quick sync's... Ctrl-C to end")
|
|
39
|
-
|
|
40
|
-
# format output
|
|
41
|
-
start = 0
|
|
42
|
-
b.trace_fields do |task, pid, cpu, flags, ts, ms|
|
|
43
|
-
start = ts.to_f if start.zero?
|
|
44
|
-
ts = ts.to_f - start
|
|
45
|
-
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
|
|
46
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
3
|
-
|
|
4
|
-
require "rbbcc"
|
|
5
|
-
include RbBCC
|
|
6
|
-
|
|
7
|
-
# load BPF program
|
|
8
|
-
b = BCC.new(text: <<BPF)
|
|
9
|
-
#include <uapi/linux/ptrace.h>
|
|
10
|
-
|
|
11
|
-
BPF_HASH(last);
|
|
12
|
-
|
|
13
|
-
int do_trace(struct pt_regs *ctx) {
|
|
14
|
-
u64 ts, *tsp, delta, key = 0, counter_key = 1, zero = 0;
|
|
15
|
-
|
|
16
|
-
// initialize counter key
|
|
17
|
-
if (last.lookup_or_try_init(&counter_key, &zero))
|
|
18
|
-
last.increment(counter_key);
|
|
19
|
-
|
|
20
|
-
// attempt to read stored timestamp
|
|
21
|
-
tsp = last.lookup(&key);
|
|
22
|
-
if (tsp != 0) {
|
|
23
|
-
delta = bpf_ktime_get_ns() - *tsp;
|
|
24
|
-
if (delta < 1000000000) {
|
|
25
|
-
// output if time is less than 1 second
|
|
26
|
-
bpf_trace_printk("%d\\n", delta / 1000000);
|
|
27
|
-
}
|
|
28
|
-
last.delete(&key);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// update stored timestamp
|
|
32
|
-
ts = bpf_ktime_get_ns();
|
|
33
|
-
last.update(&key, &ts);
|
|
34
|
-
return 0;
|
|
35
|
-
}
|
|
36
|
-
BPF
|
|
37
|
-
|
|
38
|
-
COUNTER_KEY = 1
|
|
39
|
-
|
|
40
|
-
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
|
41
|
-
puts("Tracing for quick sync's... Ctrl-C to end")
|
|
42
|
-
|
|
43
|
-
# format output
|
|
44
|
-
start = 0
|
|
45
|
-
begin
|
|
46
|
-
b.trace_fields do |task, pid, cpu, flags, ts, ms|
|
|
47
|
-
start = ts.to_f if start.zero?
|
|
48
|
-
ts = ts.to_f - start
|
|
49
|
-
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
|
|
50
|
-
end
|
|
51
|
-
rescue Interrupt
|
|
52
|
-
table = b["last"]
|
|
53
|
-
puts "Count of sys_sync: %d" % table[COUNTER_KEY].to_bcc_value
|
|
54
|
-
end
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
3
|
-
# disksnoop.rb Trace block device I/O: basic version of iosnoop.
|
|
4
|
-
# For Linux, uses BCC, eBPF. Embedded C.
|
|
5
|
-
# This is ported from original disksnoop.py
|
|
6
|
-
#
|
|
7
|
-
# Written as a basic example of tracing latency.
|
|
8
|
-
#
|
|
9
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
10
|
-
#
|
|
11
|
-
# 11-Aug-2015 Brendan Gregg Created disksnoop.py
|
|
12
|
-
|
|
13
|
-
require 'rbbcc'
|
|
14
|
-
include RbBCC
|
|
15
|
-
|
|
16
|
-
REQ_WRITE = 1 # from include/linux/blk_types.h
|
|
17
|
-
|
|
18
|
-
# load BPF program
|
|
19
|
-
b = BCC.new(text: <<CLANG)
|
|
20
|
-
#include <uapi/linux/ptrace.h>
|
|
21
|
-
#include <linux/blkdev.h>
|
|
22
|
-
|
|
23
|
-
BPF_HASH(start, struct request *);
|
|
24
|
-
|
|
25
|
-
void trace_start(struct pt_regs *ctx, struct request *req) {
|
|
26
|
-
// stash start timestamp by request ptr
|
|
27
|
-
u64 ts = bpf_ktime_get_ns();
|
|
28
|
-
|
|
29
|
-
start.update(&req, &ts);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
void trace_completion(struct pt_regs *ctx, struct request *req) {
|
|
33
|
-
u64 *tsp, delta;
|
|
34
|
-
|
|
35
|
-
tsp = start.lookup(&req);
|
|
36
|
-
if (tsp != 0) {
|
|
37
|
-
delta = bpf_ktime_get_ns() - *tsp;
|
|
38
|
-
bpf_trace_printk("%d %x %d\\n", req->__data_len,
|
|
39
|
-
req->cmd_flags, delta / 1000);
|
|
40
|
-
start.delete(&req);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
CLANG
|
|
44
|
-
|
|
45
|
-
b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
|
|
46
|
-
b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
|
|
47
|
-
b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
|
|
48
|
-
|
|
49
|
-
# header
|
|
50
|
-
puts("%-18s %-2s %-7s %8s" % ["TIME(s)", "T", "BYTES", "LAT(ms)"])
|
|
51
|
-
|
|
52
|
-
# format output
|
|
53
|
-
loop do
|
|
54
|
-
begin
|
|
55
|
-
task, pid, cpu, flags, ts, msg = b.trace_fields
|
|
56
|
-
bytes_s, bflags_s, us_s = msg.split
|
|
57
|
-
|
|
58
|
-
if (bflags_s.to_i(16) & REQ_WRITE).nonzero?
|
|
59
|
-
type_s = "W"
|
|
60
|
-
elsif bytes_s == "0" # see blk_fill_rwbs() for logic
|
|
61
|
-
type_s = "M"
|
|
62
|
-
else
|
|
63
|
-
type_s = "R"
|
|
64
|
-
end
|
|
65
|
-
ms = us_s.to_i.to_f / 1000
|
|
66
|
-
|
|
67
|
-
puts("%-18.9f %-2s %-7s %8.2f" % [ts, type_s, bytes_s, ms])
|
|
68
|
-
rescue Interrupt
|
|
69
|
-
exit
|
|
70
|
-
end
|
|
71
|
-
end
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
3
|
-
# This is a Hello World example that uses BPF_PERF_OUTPUT.
|
|
4
|
-
# Ported from hello_perf_output.py
|
|
5
|
-
|
|
6
|
-
require 'rbbcc'
|
|
7
|
-
include RbBCC
|
|
8
|
-
|
|
9
|
-
# define BPF program
|
|
10
|
-
prog = """
|
|
11
|
-
#include <linux/sched.h>
|
|
12
|
-
|
|
13
|
-
// define output data structure in C
|
|
14
|
-
struct data_t {
|
|
15
|
-
u32 pid;
|
|
16
|
-
u64 ts;
|
|
17
|
-
char comm[TASK_COMM_LEN];
|
|
18
|
-
};
|
|
19
|
-
BPF_PERF_OUTPUT(events);
|
|
20
|
-
|
|
21
|
-
int hello(struct pt_regs *ctx) {
|
|
22
|
-
struct data_t data = {};
|
|
23
|
-
|
|
24
|
-
data.pid = bpf_get_current_pid_tgid();
|
|
25
|
-
data.ts = bpf_ktime_get_ns();
|
|
26
|
-
bpf_get_current_comm(&data.comm, sizeof(data.comm));
|
|
27
|
-
|
|
28
|
-
events.perf_submit(ctx, &data, sizeof(data));
|
|
29
|
-
|
|
30
|
-
return 0;
|
|
31
|
-
}
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
# load BPF program
|
|
35
|
-
b = BCC.new(text: prog)
|
|
36
|
-
b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
|
|
37
|
-
|
|
38
|
-
# header
|
|
39
|
-
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
|
|
40
|
-
|
|
41
|
-
# process event
|
|
42
|
-
start = 0
|
|
43
|
-
print_event = lambda { |cpu, data, size|
|
|
44
|
-
event = b["events"].event(data)
|
|
45
|
-
if start == 0
|
|
46
|
-
start = event.ts
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
time_s = ((event.ts - start).to_f) / 1000000000
|
|
50
|
-
puts("%-18.9f %-16s %-6d %s" % [time_s, event.comm, event.pid,
|
|
51
|
-
"Hello, perf_output!"])
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
# loop with callback to print_event
|
|
55
|
-
b["events"].open_perf_buffer(&print_event)
|
|
56
|
-
|
|
57
|
-
loop do
|
|
58
|
-
b.perf_buffer_poll()
|
|
59
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
3
|
-
|
|
4
|
-
require "rbbcc"
|
|
5
|
-
include RbBCC
|
|
6
|
-
|
|
7
|
-
# load BPF program
|
|
8
|
-
b = BCC.new(text: <<BPF)
|
|
9
|
-
#include <uapi/linux/ptrace.h>
|
|
10
|
-
|
|
11
|
-
struct data_t {
|
|
12
|
-
u32 pid;
|
|
13
|
-
u64 ts;
|
|
14
|
-
u64 delta;
|
|
15
|
-
};
|
|
16
|
-
BPF_PERF_OUTPUT(events);
|
|
17
|
-
BPF_HASH(last);
|
|
18
|
-
|
|
19
|
-
int do_trace(struct pt_regs *ctx) {
|
|
20
|
-
u64 ts, *tsp, delta, key = 0;
|
|
21
|
-
|
|
22
|
-
// attempt to read stored timestamp
|
|
23
|
-
tsp = last.lookup(&key);
|
|
24
|
-
if (tsp != 0) {
|
|
25
|
-
struct data_t data = {};
|
|
26
|
-
delta = bpf_ktime_get_ns() - *tsp;
|
|
27
|
-
if (delta < 1000000000) {
|
|
28
|
-
data.pid = bpf_get_current_pid_tgid();
|
|
29
|
-
data.ts = bpf_ktime_get_ns();
|
|
30
|
-
data.delta = delta;
|
|
31
|
-
events.perf_submit(ctx, &data, sizeof(data));
|
|
32
|
-
}
|
|
33
|
-
last.delete(&key);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// update stored timestamp
|
|
37
|
-
ts = bpf_ktime_get_ns();
|
|
38
|
-
last.update(&key, &ts);
|
|
39
|
-
return 0;
|
|
40
|
-
}
|
|
41
|
-
BPF
|
|
42
|
-
|
|
43
|
-
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
|
44
|
-
puts("Tracing for quick sync's... Ctrl-C to end")
|
|
45
|
-
|
|
46
|
-
# format output
|
|
47
|
-
start = 0
|
|
48
|
-
b["events"].open_perf_buffer do |_, data, _|
|
|
49
|
-
event = b["events"].event(data)
|
|
50
|
-
if start == 0
|
|
51
|
-
start = event.ts
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
time_s = ((event.ts - start).to_f) / 1_000_000_000
|
|
55
|
-
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [time_s, event.delta / 1_000_000])
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
loop do
|
|
59
|
-
b.perf_buffer_poll()
|
|
60
|
-
end
|
data/docs/answers/09-bitehist.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
3
|
-
|
|
4
|
-
require 'rbbcc'
|
|
5
|
-
include RbBCC
|
|
6
|
-
|
|
7
|
-
# load BPF program
|
|
8
|
-
b = BCC.new(text: <<BPF)
|
|
9
|
-
#include <uapi/linux/ptrace.h>
|
|
10
|
-
#include <linux/blkdev.h>
|
|
11
|
-
|
|
12
|
-
BPF_HISTOGRAM(dist);
|
|
13
|
-
|
|
14
|
-
int kprobe__blk_account_io_completion(struct pt_regs *ctx, struct request *req)
|
|
15
|
-
{
|
|
16
|
-
dist.increment(bpf_log2l(req->__data_len / 1024));
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
BPF
|
|
20
|
-
|
|
21
|
-
# header
|
|
22
|
-
puts("Tracing... Hit Ctrl-C to end.")
|
|
23
|
-
|
|
24
|
-
# trace until Ctrl-C
|
|
25
|
-
begin
|
|
26
|
-
loop { sleep 0.1 }
|
|
27
|
-
rescue Interrupt
|
|
28
|
-
puts
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# output
|
|
32
|
-
b["dist"].print_log2_hist("kbytes")
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
3
|
-
|
|
4
|
-
require 'rbbcc'
|
|
5
|
-
include RbBCC
|
|
6
|
-
|
|
7
|
-
b = BCC.new(text: <<BPF)
|
|
8
|
-
#include <uapi/linux/ptrace.h>
|
|
9
|
-
#include <linux/blkdev.h>
|
|
10
|
-
|
|
11
|
-
BPF_HASH(start, struct request *);
|
|
12
|
-
BPF_HISTOGRAM(dist);
|
|
13
|
-
|
|
14
|
-
// note this program mixes R/W
|
|
15
|
-
// For next step, handle req->cmd_flags and prepare hist hash per op.
|
|
16
|
-
|
|
17
|
-
void trace_start(struct pt_regs *ctx, struct request *req) {
|
|
18
|
-
// stash start timestamp by request ptr
|
|
19
|
-
u64 ts = bpf_ktime_get_ns();
|
|
20
|
-
|
|
21
|
-
start.update(&req, &ts);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
void trace_completion(struct pt_regs *ctx, struct request *req) {
|
|
25
|
-
u64 *tsp, delta;
|
|
26
|
-
|
|
27
|
-
tsp = start.lookup(&req);
|
|
28
|
-
if (tsp != 0) {
|
|
29
|
-
delta = bpf_ktime_get_ns() - *tsp;
|
|
30
|
-
dist.increment(bpf_log2l(delta / 1000)); // us
|
|
31
|
-
start.delete(&req);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
BPF
|
|
35
|
-
|
|
36
|
-
b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
|
|
37
|
-
b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
|
|
38
|
-
b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
|
|
39
|
-
|
|
40
|
-
# header
|
|
41
|
-
puts("Tracing... Hit Ctrl-C to end.")
|
|
42
|
-
|
|
43
|
-
# trace until Ctrl-C
|
|
44
|
-
begin
|
|
45
|
-
loop { sleep 0.1 }
|
|
46
|
-
rescue Interrupt
|
|
47
|
-
puts
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# output
|
|
51
|
-
b["dist"].print_log2_hist("usec")
|