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
74347318
Commit
74347318
authored
Aug 25, 2016
by
Mark Drayton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fileslower/filetop: use de->d_name.name, add filtering
parent
4ebb7cf1
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
92 additions
and
55 deletions
+92
-55
man/man8/fileslower.8
man/man8/fileslower.8
+4
-1
man/man8/filetop.8
man/man8/filetop.8
+6
-2
tools/fileslower.py
tools/fileslower.py
+33
-20
tools/fileslower_example.txt
tools/fileslower_example.txt
+2
-1
tools/filetop.py
tools/filetop.py
+38
-21
tools/filetop_example.txt
tools/filetop_example.txt
+9
-10
No files found.
man/man8/fileslower.8
View file @
74347318
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
.SH NAME
.SH NAME
fileslower \- Trace slow synchronous file reads and writes.
fileslower \- Trace slow synchronous file reads and writes.
.SH SYNOPSIS
.SH SYNOPSIS
.B fileslower [\-h] [\-p PID] [min_ms]
.B fileslower [\-h] [\-p PID] [
-a] [
min_ms]
.SH DESCRIPTION
.SH DESCRIPTION
This script uses kernel dynamic tracing of synchronous reads and writes
This script uses kernel dynamic tracing of synchronous reads and writes
at the VFS interface, to identify slow file reads and writes for any file
at the VFS interface, to identify slow file reads and writes for any file
...
@@ -30,6 +30,9 @@ CONFIG_BPF and bcc.
...
@@ -30,6 +30,9 @@ CONFIG_BPF and bcc.
\-p PID
\-p PID
Trace this PID only.
Trace this PID only.
.TP
.TP
\-a
Include non-regular file types in output (sockets, FIFOs, etc).
.TP
min_ms
min_ms
Minimum I/O latency (duration) to trace, in milliseconds. Default is 10 ms.
Minimum I/O latency (duration) to trace, in milliseconds. Default is 10 ms.
.SH EXAMPLES
.SH EXAMPLES
...
...
man/man8/filetop.8
View file @
74347318
...
@@ -4,11 +4,12 @@ filetop \- File reads and writes by filename and process. Top for files.
...
@@ -4,11 +4,12 @@ filetop \- File reads and writes by filename and process. Top for files.
.SH SYNOPSIS
.SH SYNOPSIS
.B filetop [\-h] [\-C] [\-r MAXROWS] [\-p PID] [interval] [count]
.B filetop [\-h] [\-C] [\-r MAXROWS] [\-p PID] [interval] [count]
.SH DESCRIPTION
.SH DESCRIPTION
This is top for files.
This is top for files.
This traces file reads and writes, and prints a per-file summary every
This traces file reads and writes, and prints a per-file summary every
interval (by default, 1 second). The summary is sorted on the highest read
interval (by default, 1 second). The summary is sorted on the highest read
throughput (Kbytes).
throughput (Kbytes). By default only IO on regular files is shown. The -a
option will list all file types (sokets, FIFOs, etc).
This uses in-kernel eBPF maps to store per process summaries for efficiency.
This uses in-kernel eBPF maps to store per process summaries for efficiency.
...
@@ -29,6 +30,9 @@ Since this uses BPF, only the root user can use this tool.
...
@@ -29,6 +30,9 @@ Since this uses BPF, only the root user can use this tool.
CONFIG_BPF and bcc.
CONFIG_BPF and bcc.
.SH OPTIONS
.SH OPTIONS
.TP
.TP
\-a
Include non-regular file types (sockets, FIFOs, etc).
.TP
\-C
\-C
Don't clear the screen.
Don't clear the screen.
.TP
.TP
...
...
tools/fileslower.py
View file @
74347318
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
# fileslower Trace slow synchronous file reads and writes.
# fileslower Trace slow synchronous file reads and writes.
# For Linux, uses BCC, eBPF.
# For Linux, uses BCC, eBPF.
#
#
# USAGE: fileslower [-h] [-p PID] [min_ms]
# USAGE: fileslower [-h] [-p PID] [
-a] [
min_ms]
#
#
# This script uses kernel dynamic tracing of synchronous reads and writes
# This script uses kernel dynamic tracing of synchronous reads and writes
# at the VFS interface, to identify slow file reads and writes for any file
# at the VFS interface, to identify slow file reads and writes for any file
...
@@ -32,7 +32,6 @@ from __future__ import print_function
...
@@ -32,7 +32,6 @@ from __future__ import print_function
from
bcc
import
BPF
from
bcc
import
BPF
import
argparse
import
argparse
import
ctypes
as
ct
import
ctypes
as
ct
import
signal
import
time
import
time
# arguments
# arguments
...
@@ -45,19 +44,17 @@ parser = argparse.ArgumentParser(
...
@@ -45,19 +44,17 @@ parser = argparse.ArgumentParser(
description
=
"Trace slow synchronous file reads and writes"
,
description
=
"Trace slow synchronous file reads and writes"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
epilog
=
examples
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
parser
.
add_argument
(
"-p"
,
"--pid"
,
type
=
int
,
metavar
=
"PID"
,
dest
=
"tgid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
parser
.
add_argument
(
"-a"
,
"--all-files"
,
action
=
"store_true"
,
help
=
"include non-regular file types (sockets, FIFOs, etc)"
)
parser
.
add_argument
(
"min_ms"
,
nargs
=
"?"
,
default
=
'10'
,
parser
.
add_argument
(
"min_ms"
,
nargs
=
"?"
,
default
=
'10'
,
help
=
"minimum I/O duration to trace, in ms (default 10)"
)
help
=
"minimum I/O duration to trace, in ms (default 10)"
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
min_ms
=
int
(
args
.
min_ms
)
min_ms
=
int
(
args
.
min_ms
)
pid
=
args
.
p
id
tgid
=
args
.
tg
id
debug
=
0
debug
=
0
# signal handler
def
signal_ignore
(
signal
,
frame
):
print
()
# define BPF program
# define BPF program
bpf_text
=
"""
bpf_text
=
"""
#include <uapi/linux/ptrace.h>
#include <uapi/linux/ptrace.h>
...
@@ -72,6 +69,8 @@ enum trace_mode {
...
@@ -72,6 +69,8 @@ enum trace_mode {
struct val_t {
struct val_t {
u32 sz;
u32 sz;
u64 ts;
u64 ts;
u32 name_len;
// de->d_name.name may point to de->d_iname so limit len accordingly
char name[DNAME_INLINE_LEN];
char name[DNAME_INLINE_LEN];
char comm[TASK_COMM_LEN];
char comm[TASK_COMM_LEN];
};
};
...
@@ -81,6 +80,7 @@ struct data_t {
...
@@ -81,6 +80,7 @@ struct data_t {
u32 pid;
u32 pid;
u32 sz;
u32 sz;
u64 delta_us;
u64 delta_us;
u32 name_len;
char name[DNAME_INLINE_LEN];
char name[DNAME_INLINE_LEN];
char comm[TASK_COMM_LEN];
char comm[TASK_COMM_LEN];
};
};
...
@@ -92,22 +92,25 @@ BPF_PERF_OUTPUT(events);
...
@@ -92,22 +92,25 @@ BPF_PERF_OUTPUT(events);
static int trace_rw_entry(struct pt_regs *ctx, struct file *file,
static int trace_rw_entry(struct pt_regs *ctx, struct file *file,
char __user *buf, size_t count)
char __user *buf, size_t count)
{
{
u32 pid;
u32 tgid = bpf_get_current_pid_tgid() >> 32;
if (TGID_FILTER)
pid = bpf_get_current_pid_tgid();
if (FILTER)
return 0;
return 0;
u32 pid = bpf_get_current_pid_tgid();
// skip I/O lacking a filename
// skip I/O lacking a filename
struct dentry *de = file->f_path.dentry;
struct dentry *de = file->f_path.dentry;
if (de->d_iname[0] == 0)
int mode = file->f_inode->i_mode;
if (de->d_name.len == 0 || TYPE_FILTER)
return 0;
return 0;
// store size and timestamp by pid
// store size and timestamp by pid
struct val_t val = {};
struct val_t val = {};
val.sz = count;
val.sz = count;
val.ts = bpf_ktime_get_ns();
val.ts = bpf_ktime_get_ns();
__builtin_memcpy(&val.name, de->d_iname, sizeof(val.name));
val.name_len = de->d_name.len;
bpf_probe_read(&val.name, sizeof(val.name), (void *)de->d_name.name);
bpf_get_current_comm(&val.comm, sizeof(val.comm));
bpf_get_current_comm(&val.comm, sizeof(val.comm));
entryinfo.update(&pid, &val);
entryinfo.update(&pid, &val);
...
@@ -153,6 +156,7 @@ static int trace_rw_return(struct pt_regs *ctx, int type)
...
@@ -153,6 +156,7 @@ static int trace_rw_return(struct pt_regs *ctx, int type)
data.pid = pid;
data.pid = pid;
data.sz = valp->sz;
data.sz = valp->sz;
data.delta_us = delta_us;
data.delta_us = delta_us;
data.name_len = valp->name_len;
bpf_probe_read(&data.name, sizeof(data.name), valp->name);
bpf_probe_read(&data.name, sizeof(data.name), valp->name);
bpf_probe_read(&data.comm, sizeof(data.comm), valp->comm);
bpf_probe_read(&data.comm, sizeof(data.comm), valp->comm);
events.perf_submit(ctx, &data, sizeof(data));
events.perf_submit(ctx, &data, sizeof(data));
...
@@ -172,15 +176,20 @@ int trace_write_return(struct pt_regs *ctx)
...
@@ -172,15 +176,20 @@ int trace_write_return(struct pt_regs *ctx)
"""
"""
bpf_text
=
bpf_text
.
replace
(
'MIN_US'
,
str
(
min_ms
*
1000
))
bpf_text
=
bpf_text
.
replace
(
'MIN_US'
,
str
(
min_ms
*
1000
))
if
args
.
p
id
:
if
args
.
tg
id
:
bpf_text
=
bpf_text
.
replace
(
'
FILTER'
,
'pid != %s'
%
p
id
)
bpf_text
=
bpf_text
.
replace
(
'
TGID_FILTER'
,
'tgid != %d'
%
tg
id
)
else
:
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'0'
)
bpf_text
=
bpf_text
.
replace
(
'TGID_FILTER'
,
'0'
)
if
args
.
all_files
:
bpf_text
=
bpf_text
.
replace
(
'TYPE_FILTER'
,
'0'
)
else
:
bpf_text
=
bpf_text
.
replace
(
'TYPE_FILTER'
,
'!S_ISREG(mode)'
)
if
debug
:
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# initialize BPF
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
b
=
BPF
(
text
=
bpf_text
,
)
# I'd rather trace these via new_sync_read/new_sync_write (which used to be
# I'd rather trace these via new_sync_read/new_sync_write (which used to be
# do_sync_read/do_sync_write), but those became static. So trace these from
# do_sync_read/do_sync_write), but those became static. So trace these from
...
@@ -205,6 +214,7 @@ class Data(ct.Structure):
...
@@ -205,6 +214,7 @@ class Data(ct.Structure):
(
"pid"
,
ct
.
c_uint
),
(
"pid"
,
ct
.
c_uint
),
(
"sz"
,
ct
.
c_uint
),
(
"sz"
,
ct
.
c_uint
),
(
"delta_us"
,
ct
.
c_ulonglong
),
(
"delta_us"
,
ct
.
c_ulonglong
),
(
"name_len"
,
ct
.
c_uint
),
(
"name"
,
ct
.
c_char
*
DNAME_INLINE_LEN
),
(
"name"
,
ct
.
c_char
*
DNAME_INLINE_LEN
),
(
"comm"
,
ct
.
c_char
*
TASK_COMM_LEN
),
(
"comm"
,
ct
.
c_char
*
TASK_COMM_LEN
),
]
]
...
@@ -216,7 +226,7 @@ mode_s = {
...
@@ -216,7 +226,7 @@ mode_s = {
# header
# header
print
(
"Tracing sync read/writes slower than %d ms"
%
min_ms
)
print
(
"Tracing sync read/writes slower than %d ms"
%
min_ms
)
print
(
"%-8s %-14s %-6s %1s %-7s %7s %s"
%
(
"TIME(s)"
,
"COMM"
,
"
P
ID"
,
"D"
,
print
(
"%-8s %-14s %-6s %1s %-7s %7s %s"
%
(
"TIME(s)"
,
"COMM"
,
"
T
ID"
,
"D"
,
"BYTES"
,
"LAT(ms)"
,
"FILENAME"
))
"BYTES"
,
"LAT(ms)"
,
"FILENAME"
))
start_ts
=
time
.
time
()
start_ts
=
time
.
time
()
...
@@ -225,10 +235,13 @@ def print_event(cpu, data, size):
...
@@ -225,10 +235,13 @@ def print_event(cpu, data, size):
event
=
ct
.
cast
(
data
,
ct
.
POINTER
(
Data
)).
contents
event
=
ct
.
cast
(
data
,
ct
.
POINTER
(
Data
)).
contents
ms
=
float
(
event
.
delta_us
)
/
1000
ms
=
float
(
event
.
delta_us
)
/
1000
name
=
event
.
name
if
event
.
name_len
>
DNAME_INLINE_LEN
:
name
=
name
[:
-
3
]
+
"..."
print
(
"%-8.3f %-14.14s %-6s %1s %-7s %7.2f %s"
%
(
print
(
"%-8.3f %-14.14s %-6s %1s %-7s %7.2f %s"
%
(
time
.
time
()
-
start_ts
,
event
.
comm
,
event
.
pid
,
mode_s
[
event
.
mode
],
time
.
time
()
-
start_ts
,
event
.
comm
,
event
.
pid
,
mode_s
[
event
.
mode
],
event
.
sz
,
ms
,
event
.
name
))
event
.
sz
,
ms
,
name
))
b
[
"events"
].
open_perf_buffer
(
print_event
)
b
[
"events"
].
open_perf_buffer
(
print_event
)
while
1
:
while
1
:
...
...
tools/fileslower_example.txt
View file @
74347318
...
@@ -105,7 +105,7 @@ locks, run queue latency, etc. These can be explored using other commands.
...
@@ -105,7 +105,7 @@ locks, run queue latency, etc. These can be explored using other commands.
USAGE message:
USAGE message:
# ./fileslower -h
# ./fileslower -h
usage: fileslower
[-h] [-p PID
] [min_ms]
usage: fileslower
.py [-h] [-p PID] [-a
] [min_ms]
Trace slow synchronous file reads and writes
Trace slow synchronous file reads and writes
...
@@ -115,6 +115,7 @@ positional arguments:
...
@@ -115,6 +115,7 @@ positional arguments:
optional arguments:
optional arguments:
-h, --help show this help message and exit
-h, --help show this help message and exit
-p PID, --pid PID trace this PID only
-p PID, --pid PID trace this PID only
-a, --all-files include non-regular file types
examples:
examples:
./fileslower # trace sync file I/O slower than 10 ms (default)
./fileslower # trace sync file I/O slower than 10 ms (default)
...
...
tools/filetop.py
View file @
74347318
...
@@ -32,11 +32,13 @@ parser = argparse.ArgumentParser(
...
@@ -32,11 +32,13 @@ parser = argparse.ArgumentParser(
description
=
"File reads and writes by process"
,
description
=
"File reads and writes by process"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
epilog
=
examples
)
parser
.
add_argument
(
"-a"
,
"--all-files"
,
action
=
"store_true"
,
help
=
"include non-regular file types (sockets, FIFOs, etc)"
)
parser
.
add_argument
(
"-C"
,
"--noclear"
,
action
=
"store_true"
,
parser
.
add_argument
(
"-C"
,
"--noclear"
,
action
=
"store_true"
,
help
=
"don't clear the screen"
)
help
=
"don't clear the screen"
)
parser
.
add_argument
(
"-r"
,
"--maxrows"
,
default
=
20
,
parser
.
add_argument
(
"-r"
,
"--maxrows"
,
default
=
20
,
help
=
"maximum rows to print, default 20"
)
help
=
"maximum rows to print, default 20"
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
parser
.
add_argument
(
"-p"
,
"--pid"
,
type
=
int
,
metavar
=
"PID"
,
dest
=
"tgid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
parser
.
add_argument
(
"interval"
,
nargs
=
"?"
,
default
=
1
,
parser
.
add_argument
(
"interval"
,
nargs
=
"?"
,
default
=
1
,
help
=
"output interval, in seconds"
)
help
=
"output interval, in seconds"
)
...
@@ -61,13 +63,13 @@ bpf_text = """
...
@@ -61,13 +63,13 @@ bpf_text = """
#include <uapi/linux/ptrace.h>
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>
#include <linux/blkdev.h>
#define MAX_FILE_LEN 32
// the key for the output summary
// the key for the output summary
struct info_t {
struct info_t {
u32 pid;
u32 pid;
char name[TASK_COMM_LEN];
u32 name_len;
char file[MAX_FILE_LEN];
char comm[TASK_COMM_LEN];
// de->d_name.name may point to de->d_iname so limit len accordingly
char name[DNAME_INLINE_LEN];
char type;
char type;
};
};
...
@@ -84,22 +86,23 @@ BPF_HASH(counts, struct info_t, struct val_t);
...
@@ -84,22 +86,23 @@ BPF_HASH(counts, struct info_t, struct val_t);
static int do_entry(struct pt_regs *ctx, struct file *file,
static int do_entry(struct pt_regs *ctx, struct file *file,
char __user *buf, size_t count, int is_read)
char __user *buf, size_t count, int is_read)
{
{
u32 pid;
u32 tgid = bpf_get_current_pid_tgid() >> 32;
if (TGID_FILTER)
pid = bpf_get_current_pid_tgid();
if (FILTER)
return 0;
return 0;
u32 pid = bpf_get_current_pid_tgid();
// skip I/O lacking a filename
// skip I/O lacking a filename
struct dentry *de = file->f_path.dentry;
struct dentry *de = file->f_path.dentry;
if (de->d_iname[0] == 0)
int mode = file->f_inode->i_mode;
if (de->d_name.len == 0 || TYPE_FILTER)
return 0;
return 0;
// store counts and sizes by pid & file
// store counts and sizes by pid & file
struct info_t info = {.pid = pid};
struct info_t info = {.pid = pid};
bpf_get_current_comm(&info.
name, sizeof(info.name
));
bpf_get_current_comm(&info.
comm, sizeof(info.comm
));
__builtin_memcpy(&info.file, de->d_iname, sizeof(info.file))
;
info.name_len = de->d_name.len
;
int mode = file->f_inode->i_mode
;
bpf_probe_read(&info.name, sizeof(info.name), (void *)de->d_name.name)
;
if (S_ISREG(mode)) {
if (S_ISREG(mode)) {
info.type = 'R';
info.type = 'R';
} else if (S_ISSOCK(mode)) {
} else if (S_ISSOCK(mode)) {
...
@@ -134,17 +137,28 @@ int trace_write_entry(struct pt_regs *ctx, struct file *file,
...
@@ -134,17 +137,28 @@ int trace_write_entry(struct pt_regs *ctx, struct file *file,
}
}
"""
"""
if
args
.
pid
:
if
args
.
tgid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'pid != %s'
%
args
.
pid
)
bpf_text
=
bpf_text
.
replace
(
'TGID_FILTER'
,
'tgid != %d'
%
args
.
tgid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'TGID_FILTER'
,
'0'
)
if
args
.
all_files
:
bpf_text
=
bpf_text
.
replace
(
'TYPE_FILTER'
,
'0'
)
else
:
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'0'
)
bpf_text
=
bpf_text
.
replace
(
'TYPE_FILTER'
,
'!S_ISREG(mode)'
)
if
debug
:
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# initialize BPF
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
b
=
BPF
(
text
=
bpf_text
)
b
.
attach_kprobe
(
event
=
"__vfs_read"
,
fn_name
=
"trace_read_entry"
)
b
.
attach_kprobe
(
event
=
"__vfs_read"
,
fn_name
=
"trace_read_entry"
)
b
.
attach_kprobe
(
event
=
"__vfs_write"
,
fn_name
=
"trace_write_entry"
)
try
:
b
.
attach_kprobe
(
event
=
"__vfs_write"
,
fn_name
=
"trace_write_entry"
)
except
:
# older kernels don't have __vfs_write so try vfs_write instead
b
.
attach_kprobe
(
event
=
"vfs_write"
,
fn_name
=
"trace_write_entry"
)
DNAME_INLINE_LEN
=
32
# linux/dcache.h
print
(
'Tracing... Output every %d secs. Hit Ctrl-C to end'
%
interval
)
print
(
'Tracing... Output every %d secs. Hit Ctrl-C to end'
%
interval
)
...
@@ -163,19 +177,22 @@ while 1:
...
@@ -163,19 +177,22 @@ while 1:
print
()
print
()
with
open
(
loadavg
)
as
stats
:
with
open
(
loadavg
)
as
stats
:
print
(
"%-8s loadavg: %s"
%
(
strftime
(
"%H:%M:%S"
),
stats
.
read
()))
print
(
"%-8s loadavg: %s"
%
(
strftime
(
"%H:%M:%S"
),
stats
.
read
()))
print
(
"%-6s %-16s %-6s %-6s %-7s %-7s %1s %s"
%
(
"
P
ID"
,
"COMM"
,
print
(
"%-6s %-16s %-6s %-6s %-7s %-7s %1s %s"
%
(
"
T
ID"
,
"COMM"
,
"READS"
,
"WRITES"
,
"R_Kb"
,
"W_Kb"
,
"T"
,
"FILE"
))
"READS"
,
"WRITES"
,
"R_Kb"
,
"W_Kb"
,
"T"
,
"FILE"
))
# by-
P
ID output
# by-
T
ID output
counts
=
b
.
get_table
(
"counts"
)
counts
=
b
.
get_table
(
"counts"
)
line
=
0
line
=
0
for
k
,
v
in
reversed
(
sorted
(
counts
.
items
(),
for
k
,
v
in
reversed
(
sorted
(
counts
.
items
(),
key
=
lambda
counts
:
counts
[
1
].
rbytes
)):
key
=
lambda
counts
:
counts
[
1
].
rbytes
)):
name
=
k
.
name
if
k
.
name_len
>
DNAME_INLINE_LEN
:
name
=
name
[:
-
3
]
+
"..."
# print line
# print line
print
(
"%-6d %-16s %-6d %-6d %-7d %-7d %1s %s"
%
(
k
.
pid
,
k
.
name
,
print
(
"%-6d %-16s %-6d %-6d %-7d %-7d %1s %s"
%
(
k
.
pid
,
k
.
comm
,
v
.
reads
,
v
.
writes
,
v
.
rbytes
/
1024
,
v
.
wbytes
/
1024
,
k
.
type
,
v
.
reads
,
v
.
writes
,
v
.
rbytes
/
1024
,
v
.
wbytes
/
1024
,
k
.
type
,
k
.
fil
e
))
nam
e
))
line
+=
1
line
+=
1
if
line
>=
maxrows
:
if
line
>=
maxrows
:
...
...
tools/filetop_example.txt
View file @
74347318
...
@@ -24,11 +24,9 @@ PID COMM READS WRITES R_Kb W_Kb T FILE
...
@@ -24,11 +24,9 @@ PID COMM READS WRITES R_Kb W_Kb T FILE
26628 ld 18 0 72 0 R hibernate.o
26628 ld 18 0 72 0 R hibernate.o
26628 ld 16 0 64 0 R suspend.o
26628 ld 16 0 64 0 R suspend.o
26628 ld 16 0 64 0 R snapshot.o
26628 ld 16 0 64 0 R snapshot.o
26630 cat 1 0 64 0 O null
26628 ld 16 0 64 0 R qos.o
26628 ld 16 0 64 0 R qos.o
26628 ld 13 0 52 0 R main.o
26628 ld 13 0 52 0 R main.o
26628 ld 12 0 52 0 R swap.o
26628 ld 12 0 52 0 R swap.o
12421 sshd 3 0 48 0 O ptmx
[...]
[...]
This shows various files read and written during a Linux kernel build. The
This shows various files read and written during a Linux kernel build. The
...
@@ -40,7 +38,8 @@ While not printed, the average read and write size can be calculated by
...
@@ -40,7 +38,8 @@ While not printed, the average read and write size can be calculated by
dividing R_Kb by READS, and the same for writes.
dividing R_Kb by READS, and the same for writes.
The "T" column indicates the type of the file: "R" for regular files, "S" for
The "T" column indicates the type of the file: "R" for regular files, "S" for
sockets, and "O" for other (including pipes).
sockets, and "O" for other (including pipes). By default only regular files are
shown; use the -a option to show all file types.
This script works by tracing the vfs_read() and vfs_write() functions using
This script works by tracing the vfs_read() and vfs_write() functions using
kernel dynamic tracing, which instruments explicit read and write calls. If
kernel dynamic tracing, which instruments explicit read and write calls. If
...
@@ -65,7 +64,6 @@ Tracing... Output every 1 secs. Hit Ctrl-C to end
...
@@ -65,7 +64,6 @@ Tracing... Output every 1 secs. Hit Ctrl-C to end
PID COMM READS WRITES R_Kb W_Kb T FILE
PID COMM READS WRITES R_Kb W_Kb T FILE
32672 cksum 5006 0 320384 0 R data1
32672 cksum 5006 0 320384 0 R data1
12296 sshd 2 0 32 0 O ptmx
809 run 2 0 8 0 R nsswitch.conf
809 run 2 0 8 0 R nsswitch.conf
811 run 2 0 8 0 R nsswitch.conf
811 run 2 0 8 0 R nsswitch.conf
804 chown 2 0 8 0 R nsswitch.conf
804 chown 2 0 8 0 R nsswitch.conf
...
@@ -89,13 +87,13 @@ PID COMM READS WRITES R_Kb W_Kb T FILE
...
@@ -89,13 +87,13 @@ PID COMM READS WRITES R_Kb W_Kb T FILE
848 run 2 0 8 0 R nsswitch.conf
848 run 2 0 8 0 R nsswitch.conf
[...]
[...]
This output shows a cksum command reading data1.
Note that
This output shows a cksum command reading data1.
An optional interval and optional count can also be added to the end of the
An optional interval and optional count can also be added to the end of the
command line. For example, for 1 second interval, and 3 summaries in total:
command line. For example, for 1 second interval, and 3 summaries in total:
# ./filetop -Cr 5 1 3
# ./filetop -Cr 5
-a
1 3
Tracing... Output every 1 secs. Hit Ctrl-C to end
Tracing... Output every 1 secs. Hit Ctrl-C to end
08:08:20 loadavg: 0.30 0.42 0.31 3/282 5187
08:08:20 loadavg: 0.30 0.42 0.31 3/282 5187
...
@@ -126,15 +124,15 @@ PID COMM READS WRITES R_Kb W_Kb T FILE
...
@@ -126,15 +124,15 @@ PID COMM READS WRITES R_Kb W_Kb T FILE
5227 run 2 0 8 0 R nsswitch.conf
5227 run 2 0 8 0 R nsswitch.conf
Detaching...
Detaching...
This example
has caught heavy socket I/O from an sshd process, showing up as
This example
shows the -a option to include all file types. It caught heavy
non-regular file types (the "O" for other, and "S" for socket, in the type
socket I/O from an sshd process, showing up as non-regular file types (the "O"
column: "T").
for other, and "S" for socket, in the type column: "T").
USAGE message:
USAGE message:
# ./filetop -h
# ./filetop -h
usage: filetop
[-h
] [-C] [-r MAXROWS] [-p PID] [interval] [count]
usage: filetop
.py [-h] [-a
] [-C] [-r MAXROWS] [-p PID] [interval] [count]
File reads and writes by process
File reads and writes by process
...
@@ -144,6 +142,7 @@ positional arguments:
...
@@ -144,6 +142,7 @@ positional arguments:
optional arguments:
optional arguments:
-h, --help show this help message and exit
-h, --help show this help message and exit
-a, --all-files include non-regular file types (sockets, FIFOs, etc)
-C, --noclear don't clear the screen
-C, --noclear don't clear the screen
-r MAXROWS, --maxrows MAXROWS
-r MAXROWS, --maxrows MAXROWS
maximum rows to print, default 20
maximum rows to print, default 20
...
...
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