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
f70c97fa
Commit
f70c97fa
authored
Feb 19, 2016
by
Brendan Gregg
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #402 from mcaleavya/master
Migrated filelife to bpf_perf_event
parents
b1178f6f
cfc31503
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
148 additions
and
9 deletions
+148
-9
man/man8/filelife.8
man/man8/filelife.8
+4
-0
tools/filelife.py
tools/filelife.py
+40
-9
tools/old/filelife.py
tools/old/filelife.py
+104
-0
No files found.
man/man8/filelife.8
View file @
f70c97fa
...
@@ -13,6 +13,10 @@ This works by tracing the kernel vfs_create() and vfs_delete() functions using
...
@@ -13,6 +13,10 @@ This works by tracing the kernel vfs_create() and vfs_delete() functions using
dynamic tracing, and will need updating to match any changes to these
dynamic tracing, and will need updating to match any changes to these
functions.
functions.
This makes use of a Linux 4.5 feature (bpf_perf_event_output());
for kernels older than 4.5, see the version under tools/old,
which uses an older mechanism.
Since this uses BPF, only the root user can use this tool.
Since this uses BPF, only the root user can use this tool.
.SH REQUIREMENTS
.SH REQUIREMENTS
CONFIG_BPF and bcc.
CONFIG_BPF and bcc.
...
...
tools/filelife.py
View file @
f70c97fa
...
@@ -15,11 +15,13 @@
...
@@ -15,11 +15,13 @@
# Licensed under the Apache License, Version 2.0 (the "License")
# Licensed under the Apache License, Version 2.0 (the "License")
#
#
# 08-Feb-2015 Brendan Gregg Created this.
# 08-Feb-2015 Brendan Gregg Created this.
# 17-Feb-2016 Allan McAleavy updated for BPF_PERF_OUTPUT
from
__future__
import
print_function
from
__future__
import
print_function
from
bcc
import
BPF
from
bcc
import
BPF
import
argparse
import
argparse
from
time
import
strftime
from
time
import
strftime
import
ctypes
as
ct
# arguments
# arguments
examples
=
"""examples:
examples
=
"""examples:
...
@@ -39,8 +41,17 @@ debug = 0
...
@@ -39,8 +41,17 @@ debug = 0
bpf_text
=
"""
bpf_text
=
"""
#include <uapi/linux/ptrace.h>
#include <uapi/linux/ptrace.h>
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/sched.h>
struct data_t {
u32 pid;
u64 delta;
char comm[TASK_COMM_LEN];
char fname[DNAME_INLINE_LEN];
};
BPF_HASH(birth, struct dentry *);
BPF_HASH(birth, struct dentry *);
BPF_PERF_OUTPUT(events);
// trace file creation time
// trace file creation time
int trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
int trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
...
@@ -57,7 +68,9 @@ int trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
...
@@ -57,7 +68,9 @@ int trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
// trace file deletion and output details
// trace file deletion and output details
int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
{
{
struct data_t data = {};
u32 pid = bpf_get_current_pid_tgid();
u32 pid = bpf_get_current_pid_tgid();
FILTER
FILTER
u64 *tsp, delta;
u64 *tsp, delta;
...
@@ -65,17 +78,36 @@ int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
...
@@ -65,17 +78,36 @@ int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
if (tsp == 0) {
if (tsp == 0) {
return 0; // missed create
return 0; // missed create
}
}
delta = (bpf_ktime_get_ns() - *tsp) / 1000000;
delta = (bpf_ktime_get_ns() - *tsp) / 1000000;
birth.delete(&dentry);
birth.delete(&dentry);
if (dentry->d_iname[0] == 0)
if (dentry->d_iname[0] == 0)
return 0;
return 0;
bpf_trace_printk("%d %s
\
\
n", delta, dentry->d_iname);
if (bpf_get_current_comm(&data.comm, sizeof(data.comm)) == 0) {
data.pid = pid;
data.delta = delta;
bpf_probe_read(&data.fname, sizeof(data.fname), dentry->d_iname);
}
events.perf_submit(ctx, &data, sizeof(data));
return 0;
return 0;
}
}
"""
"""
TASK_COMM_LEN
=
16
# linux/sched.h
DNAME_INLINE_LEN
=
255
# linux/dcache.h
class
Data
(
ct
.
Structure
):
_fields_
=
[
(
"pid"
,
ct
.
c_ulonglong
),
(
"delta"
,
ct
.
c_ulonglong
),
(
"comm"
,
ct
.
c_char
*
TASK_COMM_LEN
),
(
"fname"
,
ct
.
c_char
*
DNAME_INLINE_LEN
)
]
if
args
.
pid
:
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
'if (pid != %s) { return 0; }'
%
args
.
pid
)
...
@@ -92,13 +124,12 @@ b.attach_kprobe(event="vfs_unlink", fn_name="trace_unlink")
...
@@ -92,13 +124,12 @@ b.attach_kprobe(event="vfs_unlink", fn_name="trace_unlink")
# header
# header
print
(
"%-8s %-6s %-16s %-7s %s"
%
(
"TIME"
,
"PID"
,
"COMM"
,
"AGE(s)"
,
"FILE"
))
print
(
"%-8s %-6s %-16s %-7s %s"
%
(
"TIME"
,
"PID"
,
"COMM"
,
"AGE(s)"
,
"FILE"
))
start_ts
=
0
# process event
def
print_event
(
cpu
,
data
,
size
):
event
=
ct
.
cast
(
data
,
ct
.
POINTER
(
Data
)).
contents
print
(
"%-8s %-6d %-16s %-7.2f %s"
%
(
strftime
(
"%H:%M:%S"
),
event
.
pid
,
event
.
comm
,
float
(
event
.
delta
)
/
1000
,
event
.
fname
))
# format output
b
[
"events"
].
open_perf_buffer
(
print_event
)
while
1
:
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
b
.
kprobe_poll
()
(
delta
,
filename
)
=
msg
.
split
(
" "
,
1
)
# print columns
print
(
"%-8s %-6d %-16s %-7.2f %s"
%
(
strftime
(
"%H:%M:%S"
),
pid
,
task
,
float
(
delta
)
/
1000
,
filename
))
tools/old/filelife.py
0 → 100755
View file @
f70c97fa
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# filelife Trace the lifespan of short-lived files.
# For Linux, uses BCC, eBPF. Embedded C.
#
# This traces the creation and deletion of files, providing information
# on who deleted the file, the file age, and the file name. The intent is to
# provide information on short-lived files, for debugging or performance
# analysis.
#
# USAGE: filelife [-h] [-p PID]
#
# Copyright 2016 Netflix, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 08-Feb-2015 Brendan Gregg Created this.
from
__future__
import
print_function
from
bcc
import
BPF
import
argparse
from
time
import
strftime
# arguments
examples
=
"""examples:
./filelife # trace all stat() syscalls
./filelife -p 181 # only trace PID 181
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Trace stat() syscalls"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
args
=
parser
.
parse_args
()
debug
=
0
# define BPF program
bpf_text
=
"""
#include <uapi/linux/ptrace.h>
#include <linux/fs.h>
BPF_HASH(birth, struct dentry *);
// trace file creation time
int trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
{
u32 pid = bpf_get_current_pid_tgid();
FILTER
u64 ts = bpf_ktime_get_ns();
birth.update(&dentry, &ts);
return 0;
};
// trace file deletion and output details
int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
{
u32 pid = bpf_get_current_pid_tgid();
FILTER
u64 *tsp, delta;
tsp = birth.lookup(&dentry);
if (tsp == 0) {
return 0; // missed create
}
delta = (bpf_ktime_get_ns() - *tsp) / 1000000;
birth.delete(&dentry);
if (dentry->d_iname[0] == 0)
return 0;
bpf_trace_printk("%d %s
\
\
n", delta, dentry->d_iname);
return 0;
}
"""
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
debug
:
print
(
bpf_text
)
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
b
.
attach_kprobe
(
event
=
"vfs_create"
,
fn_name
=
"trace_create"
)
b
.
attach_kprobe
(
event
=
"vfs_unlink"
,
fn_name
=
"trace_unlink"
)
# header
print
(
"%-8s %-6s %-16s %-7s %s"
%
(
"TIME"
,
"PID"
,
"COMM"
,
"AGE(s)"
,
"FILE"
))
start_ts
=
0
# format output
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
delta
,
filename
)
=
msg
.
split
(
" "
,
1
)
# print columns
print
(
"%-8s %-6d %-16s %-7.2f %s"
%
(
strftime
(
"%H:%M:%S"
),
pid
,
task
,
float
(
delta
)
/
1000
,
filename
))
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