rbbcc 0.3.1 → 0.4.0
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 +2 -2
 - data/README.md +4 -0
 - data/docs/README.md +2 -0
 - data/docs/answers/01-hello-world.rb +16 -0
 - data/docs/answers/02-sys_sync.rb +18 -0
 - data/docs/answers/03-hello_fields.rb +33 -0
 - data/docs/answers/04-sync_timing.rb +46 -0
 - data/docs/answers/05-sync_count.rb +54 -0
 - data/docs/answers/06-disksnoop.rb +71 -0
 - data/docs/answers/07-hello_perf_output.rb +59 -0
 - data/docs/answers/08-sync_perf_output.rb +60 -0
 - data/docs/answers/09-bitehist.rb +32 -0
 - data/docs/answers/10-disklatency.rb +51 -0
 - data/docs/answers/11-vfsreadlat.c +46 -0
 - data/docs/answers/11-vfsreadlat.rb +66 -0
 - data/docs/answers/12-urandomread.rb +38 -0
 - data/docs/answers/13-disksnoop_fixed.rb +108 -0
 - data/docs/answers/14-strlen_count.rb +46 -0
 - data/docs/answers/15-nodejs_http_server.rb +44 -0
 - data/docs/answers/16-task_switch.c +23 -0
 - data/docs/answers/16-task_switch.rb +17 -0
 - data/docs/answers/node-server.js +11 -0
 - data/docs/projects_using_rbbcc.md +43 -0
 - data/docs/tutorial_bcc_ruby_developer.md +772 -0
 - data/lib/rbbcc/bcc.rb +41 -13
 - data/lib/rbbcc/clib.rb +1 -0
 - data/lib/rbbcc/table.rb +16 -22
 - data/lib/rbbcc/version.rb +1 -1
 - data/rbbcc.gemspec +1 -1
 - metadata +25 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 35d11d74dd0d8eacf88978ec066ede1d64aef374027d819f5891a124822db4e9
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 22125362cf25181c33b253d7c6ece7d2e9b9fa2d8933d8c7f120c453384df5d8
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: d145f5307df79f42679892b26b4f3f320dbdfb7d931f65f9f2b84ba4032d780991c2f2d0fb36a06b030bc59e45d16b4cca201d42e0368eb5ed4d4853958d44f3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 86c50507da5cc6ba947def8ce7c169937a432579ce92e0b70c0d24d4316fbba7c45a2de22d602b0c166f473db8e8fddeab1d961b07b97dd719b0a30f15fd9234
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    | 
         @@ -12,7 +12,7 @@ GEM 
     | 
|
| 
       12 
12 
     | 
    
         
             
                pry (0.12.2)
         
     | 
| 
       13 
13 
     | 
    
         
             
                  coderay (~> 1.1.0)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  method_source (~> 0.9.0)
         
     | 
| 
       15 
     | 
    
         
            -
                rake ( 
     | 
| 
      
 15 
     | 
    
         
            +
                rake (13.0.1)
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
            PLATFORMS
         
     | 
| 
       18 
18 
     | 
    
         
             
              ruby
         
     | 
| 
         @@ -21,7 +21,7 @@ DEPENDENCIES 
     | 
|
| 
       21 
21 
     | 
    
         
             
              bundler (~> 2.0)
         
     | 
| 
       22 
22 
     | 
    
         
             
              minitest
         
     | 
| 
       23 
23 
     | 
    
         
             
              pry
         
     | 
| 
       24 
     | 
    
         
            -
              rake (~>  
     | 
| 
      
 24 
     | 
    
         
            +
              rake (~> 13.0)
         
     | 
| 
       25 
25 
     | 
    
         
             
              rbbcc!
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
            BUNDLED WITH
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -94,6 +94,10 @@ $ docker run --privileged \ 
     | 
|
| 
       94 
94 
     | 
    
         
             
                        runc-5025  [003] d...  1237.797464: : Hello, World!
         
     | 
| 
       95 
95 
     | 
    
         
             
            ```
         
     | 
| 
       96 
96 
     | 
    
         | 
| 
      
 97 
     | 
    
         
            +
            ## Documents
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            See [docs/](docs/) for getting started and tutorial.
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
       97 
101 
     | 
    
         
             
            ## Development
         
     | 
| 
       98 
102 
     | 
    
         | 
| 
       99 
103 
     | 
    
         
             
            After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         
     | 
    
        data/docs/README.md
    CHANGED
    
    | 
         @@ -1,5 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # RbBCC Docs
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            * [Getting Started](getting_started.md)
         
     | 
| 
      
 4 
     | 
    
         
            +
            * [Ruby Tutorial](tutorial_bcc_ruby_developer.md)
         
     | 
| 
      
 5 
     | 
    
         
            +
            * [Projects Using RbBCC](projects_using_rbbcc.md)
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
            **Please see also [BCC itself's README](https://github.com/iovisor/bcc/#readme) and [docs](https://github.com/iovisor/bcc/tree/master/docs).** 
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 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
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 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")
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 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")
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
             * From: https://github.com/iovisor/bcc/blob/master/examples/tracing/vfsreadlat.c
         
     | 
| 
      
 3 
     | 
    
         
            +
             *
         
     | 
| 
      
 4 
     | 
    
         
            +
             * vfsreadlat.c		VFS read latency distribution.
         
     | 
| 
      
 5 
     | 
    
         
            +
             *			For Linux, uses BCC, eBPF. See .py/.rb file.
         
     | 
| 
      
 6 
     | 
    
         
            +
             *
         
     | 
| 
      
 7 
     | 
    
         
            +
             * Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
         
     | 
| 
      
 8 
     | 
    
         
            +
             * This program is free software; you can redistribute it and/or
         
     | 
| 
      
 9 
     | 
    
         
            +
             * modify it under the terms of version 2 of the GNU General Public
         
     | 
| 
      
 10 
     | 
    
         
            +
             * License as published by the Free Software Foundation.
         
     | 
| 
      
 11 
     | 
    
         
            +
             *
         
     | 
| 
      
 12 
     | 
    
         
            +
             * 15-Aug-2015	Brendan Gregg	Created this.
         
     | 
| 
      
 13 
     | 
    
         
            +
             */
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            #include <uapi/linux/ptrace.h>
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            BPF_HASH(start, u32);
         
     | 
| 
      
 18 
     | 
    
         
            +
            BPF_HISTOGRAM(dist);
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            int do_entry(struct pt_regs *ctx)
         
     | 
| 
      
 21 
     | 
    
         
            +
            {
         
     | 
| 
      
 22 
     | 
    
         
            +
              u32 pid;
         
     | 
| 
      
 23 
     | 
    
         
            +
              u64 ts, *val;
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              pid = bpf_get_current_pid_tgid();
         
     | 
| 
      
 26 
     | 
    
         
            +
              ts = bpf_ktime_get_ns();
         
     | 
| 
      
 27 
     | 
    
         
            +
              start.update(&pid, &ts);
         
     | 
| 
      
 28 
     | 
    
         
            +
              return 0;
         
     | 
| 
      
 29 
     | 
    
         
            +
            }
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            int do_return(struct pt_regs *ctx)
         
     | 
| 
      
 32 
     | 
    
         
            +
            {
         
     | 
| 
      
 33 
     | 
    
         
            +
              u32 pid;
         
     | 
| 
      
 34 
     | 
    
         
            +
              u64 *tsp, delta;
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              pid = bpf_get_current_pid_tgid();
         
     | 
| 
      
 37 
     | 
    
         
            +
              tsp = start.lookup(&pid);
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              if (tsp != 0) {
         
     | 
| 
      
 40 
     | 
    
         
            +
                delta = bpf_ktime_get_ns() - *tsp;
         
     | 
| 
      
 41 
     | 
    
         
            +
                dist.increment(bpf_log2l(delta / 1000));
         
     | 
| 
      
 42 
     | 
    
         
            +
                start.delete(&pid);
         
     | 
| 
      
 43 
     | 
    
         
            +
              }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              return 0;
         
     | 
| 
      
 46 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,66 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Original: from vfsreadlat.py
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright (c) 2015 Brendan Gregg.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License")
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Ruby version follows.
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            # vfsreadlat.rb		VFS read latency distribution.
         
     | 
| 
      
 9 
     | 
    
         
            +
            #			For Linux, uses BCC, eBPF. See .c file.
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Written as a basic example of a function latency distribution histogram.
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # USAGE: vfsreadlat.rb [interval [count]]
         
     | 
| 
      
 14 
     | 
    
         
            +
            #
         
     | 
| 
      
 15 
     | 
    
         
            +
            # The default interval is 5 seconds. A Ctrl-C will print the partially
         
     | 
| 
      
 16 
     | 
    
         
            +
            # gathered histogram then exit.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            require "rbbcc"
         
     | 
| 
      
 19 
     | 
    
         
            +
            include RbBCC
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            def usage
         
     | 
| 
      
 22 
     | 
    
         
            +
              puts("USAGE: %s [interval [count]]" % $0)
         
     | 
| 
      
 23 
     | 
    
         
            +
              exit
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            # arguments
         
     | 
| 
      
 27 
     | 
    
         
            +
            interval = 5
         
     | 
| 
      
 28 
     | 
    
         
            +
            count = -1
         
     | 
| 
      
 29 
     | 
    
         
            +
            if ARGV.size > 0
         
     | 
| 
      
 30 
     | 
    
         
            +
              begin
         
     | 
| 
      
 31 
     | 
    
         
            +
                interval = ARGV[0].to_i
         
     | 
| 
      
 32 
     | 
    
         
            +
                raise if interval == 0
         
     | 
| 
      
 33 
     | 
    
         
            +
                count = ARGV[1].to_i if ARGV[1]
         
     | 
| 
      
 34 
     | 
    
         
            +
              rescue	=> e # also catches -h, --help
         
     | 
| 
      
 35 
     | 
    
         
            +
                usage()
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            # load BPF program
         
     | 
| 
      
 40 
     | 
    
         
            +
            b = BCC.new(src_file: "11-vfsreadlat.c")
         
     | 
| 
      
 41 
     | 
    
         
            +
            b.attach_kprobe(event: "vfs_read", fn_name: "do_entry")
         
     | 
| 
      
 42 
     | 
    
         
            +
            b.attach_kretprobe(event: "vfs_read", fn_name: "do_return")
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            # header
         
     | 
| 
      
 45 
     | 
    
         
            +
            print("Tracing... Hit Ctrl-C to end.")
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            # output
         
     | 
| 
      
 48 
     | 
    
         
            +
            cycle = 0
         
     | 
| 
      
 49 
     | 
    
         
            +
            do_exit = false
         
     | 
| 
      
 50 
     | 
    
         
            +
            loop do
         
     | 
| 
      
 51 
     | 
    
         
            +
              if count > 0
         
     | 
| 
      
 52 
     | 
    
         
            +
                cycle += 1
         
     | 
| 
      
 53 
     | 
    
         
            +
                exit if cycle > count
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
              begin
         
     | 
| 
      
 57 
     | 
    
         
            +
                sleep(interval)
         
     | 
| 
      
 58 
     | 
    
         
            +
              rescue Interrupt
         
     | 
| 
      
 59 
     | 
    
         
            +
                do_exit = true
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              puts
         
     | 
| 
      
 63 
     | 
    
         
            +
              b["dist"].print_log2_hist("usecs")
         
     | 
| 
      
 64 
     | 
    
         
            +
              b["dist"].clear
         
     | 
| 
      
 65 
     | 
    
         
            +
              exit if do_exit
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # urandomread.rb Example of instrumenting a kernel tracepoint.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #                For Linux, uses BCC, BPF. Embedded C.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support).
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Test by running this, then in another shell, run:
         
     | 
| 
      
 9 
     | 
    
         
            +
            #     dd if=/dev/urandom of=/dev/null bs=1k count=5
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Original urandomread.py Copyright 2016 Netflix, Inc.
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License")
         
     | 
| 
      
 13 
     | 
    
         
            +
            # Ruby version follows.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            require 'rbbcc'
         
     | 
| 
      
 16 
     | 
    
         
            +
            include RbBCC
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            b = BCC.new(text: <<BPF)
         
     | 
| 
      
 19 
     | 
    
         
            +
            TRACEPOINT_PROBE(random, urandom_read) {
         
     | 
| 
      
 20 
     | 
    
         
            +
                // args is from /sys/kernel/debug/tracing/events/random/urandom_read/format
         
     | 
| 
      
 21 
     | 
    
         
            +
                bpf_trace_printk("%d\\n", args->got_bits);
         
     | 
| 
      
 22 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 23 
     | 
    
         
            +
            }
         
     | 
| 
      
 24 
     | 
    
         
            +
            BPF
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            # header
         
     | 
| 
      
 27 
     | 
    
         
            +
            puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "GOTBITS"])
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            # format output
         
     | 
| 
      
 30 
     | 
    
         
            +
            loop do
         
     | 
| 
      
 31 
     | 
    
         
            +
              begin
         
     | 
| 
      
 32 
     | 
    
         
            +
                b.trace_fields do |task, pid, cpu, flags, ts, msg|
         
     | 
| 
      
 33 
     | 
    
         
            +
                  puts("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              rescue Interrupt
         
     | 
| 
      
 36 
     | 
    
         
            +
                exit
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     |