我需要了解哪些文件占用了我硬盘的iops。只需使用" strace"不会解决我的问题。我想知道,哪些文件真正写入光盘,而不是页面缓存。我尝试使用" systemtap",但我无法理解如何找出哪些文件(文件名或inode)消耗我的iops。有什么工具可以解决我的问题吗?
答案 0 :(得分:2)
是的,您绝对可以使用 SystemTap 进行追踪。当上层(通常是VFS子系统)想要发出I / O操作时,它将调用submit_bio
和generic_make_request
函数。请注意,这些并不意味着单个物理I / O操作。例如,来自相邻扇区的写入可以由I / O调度程序合并。
诀窍是如何在generic_make_request
中确定文件路径名。读取非常简单,因为此函数将在与read()
调用相同的上下文中调用。写入通常是异步的,因此write()
将简单地更新页面缓存条目并将其标记为脏,而submit_bio
由一个没有原始调用进程信息的回写内核线程调用:
可以通过查看page
结构中的bio
引用来推断写作 - 它具有mapping
struct address_space
。对应于打开文件的struct file
还包含f_mapping
,它指向同一个address_space实例,并且它还指向包含文件名称的dentry
(这可以通过使用{{3}来完成}})
因此我们需要两个探测器:一个用于捕获读取/写入文件的尝试并将路径和address_space
保存到关联数组中,另一个用于捕获generic_make_request
个调用(这由探测器{{执行3}})。
这是一个计算IOPS的示例脚本:
// maps struct address_space to path name
global paths;
// IOPS per file
global iops;
// Capture attempts to read and write by VFS
probe kernel.function("vfs_read"),
kernel.function("vfs_write") {
mapping = $file->f_mapping;
// Assemble full path name for running task (task_current())
// from open file "$file" of type "struct file"
path = task_dentry_path(task_current(), $file->f_path->dentry,
$file->f_path->mnt);
paths[mapping] = path;
}
// Attach to generic_make_request()
probe ioblock.request {
for (i = 0; i < $bio->bi_vcnt ; i++) {
// Each BIO request may have more than one page
// to write
page = $bio->bi_io_vec[i]->bv_page;
mapping = @cast(page, "struct page")->mapping;
iops[paths[mapping], rw] <<< 1;
}
}
// Once per second drain iops statistics
probe timer.s(1) {
println(ctime());
foreach([path+, rw] in iops) {
printf("%3d %s %s\n", @count(iops[path, rw]),
bio_rw_str(rw), path);
}
delete iops
}
此示例脚本适用于XFS,但需要更新以支持AIO和卷管理器(包括btrfs)。另外,我不确定它将如何处理元数据读写,但这是一个良好的开端;)
如果您想了解有关SystemTap的更多信息,可以查看我的书:task_dentry_path
答案 1 :(得分:0)
也许iotop会给你一个关于哪个进程正在进行I / O的提示,因此你对相关文件有所了解。
iotop --only
--only选项用于仅查看实际执行I / O的进程或线程,而不是显示所有进程或线程