Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
75291d00
Commit
75291d00
authored
Apr 20, 2016
by
Mark Drayton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lua ports of biosnoop and stacksnoop
parent
ba275e4c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
275 additions
and
0 deletions
+275
-0
tools/biosnoop.lua
tools/biosnoop.lua
+183
-0
tools/stacksnoop.lua
tools/stacksnoop.lua
+92
-0
No files found.
tools/biosnoop.lua
0 → 100644
View file @
75291d00
#!/usr/bin/env bcc-lua
--[[
Copyright 2016 GitHub, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--]]
local
program
=
[[
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>
struct val_t {
u32 pid;
char name[TASK_COMM_LEN];
};
struct data_t {
u32 pid;
u64 rwflag;
u64 delta;
u64 sector;
u64 len;
u64 ts;
char disk_name[DISK_NAME_LEN];
char name[TASK_COMM_LEN];
};
BPF_HASH(start, struct request *);
BPF_HASH(infobyreq, struct request *, struct val_t);
BPF_PERF_OUTPUT(events);
// cache PID and comm by-req
int trace_pid_start(struct pt_regs *ctx, struct request *req)
{
struct val_t val = {};
if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) {
val.pid = bpf_get_current_pid_tgid();
infobyreq.update(&req, &val);
}
return 0;
}
// time block I/O
int trace_req_start(struct pt_regs *ctx, struct request *req)
{
u64 ts;
ts = bpf_ktime_get_ns();
start.update(&req, &ts);
return 0;
}
// output
int trace_req_completion(struct pt_regs *ctx, struct request *req)
{
u64 *tsp, delta;
u32 *pidp = 0;
struct val_t *valp;
struct data_t data ={};
u64 ts;
// fetch timestamp and calculate delta
tsp = start.lookup(&req);
if (tsp == 0) {
// missed tracing issue
return 0;
}
ts = bpf_ktime_get_ns();
data.delta = ts - *tsp;
data.ts = ts / 1000;
valp = infobyreq.lookup(&req);
if (valp == 0) {
data.len = req->__data_len;
strcpy(data.name,"?");
} else {
data.pid = valp->pid;
data.len = req->__data_len;
data.sector = req->__sector;
bpf_probe_read(&data.name, sizeof(data.name), valp->name);
bpf_probe_read(&data.disk_name, sizeof(data.disk_name),
req->rq_disk->disk_name);
}
if (req->cmd_flags & REQ_WRITE) {
data.rwflag=1;
} else {
data.rwflag=0;
}
events.perf_submit(ctx,&data,sizeof(data));
start.delete(&req);
infobyreq.delete(&req);
return 0;
}
]]
local
ffi
=
require
(
"ffi"
)
return
function
(
BPF
,
utils
)
local
bpf
=
BPF
:
new
{
text
=
program
}
bpf
:
attach_kprobe
{
event
=
"blk_account_io_start"
,
fn_name
=
"trace_pid_start"
}
bpf
:
attach_kprobe
{
event
=
"blk_start_request"
,
fn_name
=
"trace_req_start"
}
bpf
:
attach_kprobe
{
event
=
"blk_mq_start_request"
,
fn_name
=
"trace_req_start"
}
bpf
:
attach_kprobe
{
event
=
"blk_account_io_completion"
,
fn_name
=
"trace_req_completion"
}
print
(
"%-14s %-14s %-6s %-7s %-2s %-9s %-7s %7s"
%
{
"TIME(s)"
,
"COMM"
,
"PID"
,
"DISK"
,
"T"
,
"SECTOR"
,
"BYTES"
,
"LAT(ms)"
})
local
rwflg
=
""
local
start_ts
=
0
local
prev_ts
=
0
local
delta
=
0
local
function
print_event
(
cpu
,
event
)
local
val
=
-
1
local
event_pid
=
event
.
pid
local
event_delta
=
tonumber
(
event
.
delta
)
local
event_sector
=
tonumber
(
event
.
sector
)
local
event_len
=
tonumber
(
event
.
len
)
local
event_ts
=
tonumber
(
event
.
ts
)
local
event_disk_name
=
ffi
.
string
(
event
.
disk_name
)
local
event_name
=
ffi
.
string
(
event
.
name
)
if
event
.
rwflag
==
1
then
rwflg
=
"W"
end
if
event
.
rwflag
==
0
then
rwflg
=
"R"
end
if
not
event_name
:
match
(
"%?"
)
then
val
=
event_sector
end
if
start_ts
==
0
then
prev_ts
=
start_ts
end
if
start_ts
==
1
then
delta
=
delta
+
(
event_ts
-
prev_ts
)
end
print
(
"%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f"
%
{
delta
/
1000000
,
event_name
,
event_pid
,
event_disk_name
,
rwflg
,
val
,
event_len
,
event_delta
/
1000000
})
prev_ts
=
event_ts
start_ts
=
1
end
local
TASK_COMM_LEN
=
16
-- linux/sched.h
local
DISK_NAME_LEN
=
32
-- linux/genhd.h
bpf
:
get_table
(
"events"
):
open_perf_buffer
(
print_event
,
[[
struct {
uint32_t pid;
uint64_t rwflag;
uint64_t delta;
uint64_t sector;
uint64_t len;
uint64_t ts;
char disk_name[%d];
char name[%d];
}
]]
%
{
DISK_NAME_LEN
,
TASK_COMM_LEN
})
bpf
:
kprobe_poll_loop
()
end
tools/stacksnoop.lua
0 → 100644
View file @
75291d00
#!/usr/bin/env bcc-lua
--[[
Copyright 2016 GitHub, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--]]
local
program
=
[[
#include <uapi/linux/ptrace.h>
BPF_STACK_TRACE(stack_traces, 128)
void trace_stack(struct pt_regs *ctx) {
FILTER
int stack_id = stack_traces.get_stackid(ctx, BPF_F_REUSE_STACKID);
if (stack_id >= 0)
bpf_trace_printk("stack_id=%d\n", stack_id);
}
]]
return
function
(
BPF
,
utils
)
local
parser
=
utils
.
argparse
(
"stacksnoop"
,
"Trace and print kernel stack traces for a kernel function"
)
parser
:
flag
(
"-s --offset"
)
parser
:
flag
(
"-v --verbose"
)
parser
:
option
(
"-p --pid"
):
convert
(
tonumber
)
parser
:
argument
(
"function"
,
"kernel function name"
):
target
(
"fn"
)
local
args
=
parser
:
parse
()
local
ksym
=
BPF
.
SymbolCache
()
local
filter
=
""
if
args
.
pid
then
filter
=
[[
u32 pid;
pid = bpf_get_current_pid_tgid();
if (pid != %d) { return; }
]]
%
args
.
pid
end
local
text
=
program
:
gsub
(
"FILTER"
,
filter
)
local
bpf
=
BPF
:
new
{
text
=
text
}
bpf
:
attach_kprobe
{
event
=
args
.
fn
,
fn_name
=
"trace_stack"
}
if
BPF
.
num_open_kprobes
()
==
0
then
print
(
"Function \"
%
s
\
" not found. Exiting."
%
args
.
fn
)
return
end
if
args
.
verbose
then
print
(
"%-18s %-12s %-6s %-3s %s"
%
{
"TIME(s)"
,
"COMM"
,
"PID"
,
"CPU"
,
"SYSCALL"
})
else
print
(
"%-18s %s"
%
{
"TIME(s)"
,
"SYSCALL"
})
end
local
stack_traces
=
bpf
:
get_table
(
"stack_traces"
)
local
pipe
=
bpf
:
pipe
()
while
true
do
local
task
,
pid
,
cpu
,
flags
,
ts
,
msg
=
pipe
:
trace_fields
()
local
stack_id
=
string.match
(
msg
,
"stack_id=(%d+)"
)
if
stack_id
then
if
args
.
verbose
then
print
(
"%-18.9f %-12.12s %-6d %-3d %s"
%
{
ts
,
task
,
pid
,
cpu
,
args
.
fn
})
else
print
(
"%-18.9f %s"
%
{
ts
,
args
.
fn
})
end
for
addr
in
stack_traces
:
walk
(
tonumber
(
stack_id
))
do
local
sym
,
offset
=
ksym
:
resolve
(
addr
)
if
args
.
offset
then
print
(
"
\t
%-16p %s+0x%x"
%
{
addr
,
sym
,
tonumber
(
offset
)})
else
print
(
"
\t
%-16p %s"
%
{
addr
,
sym
})
end
end
end
print
()
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment