如何监视哪些文件消耗iops?

我需要了解哪些文件消耗我的硬盘的iops。 只是使用“strace”不会解决我的问题。 我想知道,哪些文件是真正写入光盘,而不是页面caching。 我试图使用“systemtap”,但我不明白如何找出哪些文件(文件名或inode)消耗我的iops。 有什么工具可以解决我的问题吗?

是的,你绝对可以使用SystemTap来追踪它。 当上层(通常是VFS子系统)想要发布I / O操作时,它将调用submit_biogeneric_make_request函数。 请注意,这些并不意味着单个物理I / O操作。 例如,来自相邻扇区的写入可以被I / O调度器合并。

诀窍是如何确定generic_make_request文件路径名。 读操作非常简单,因为这个函数和read()调用在同一个上下文中被调用。 写入通常是异步的,所以write()将简单地更新页面缓存项并将其标记为脏,而submit_bio被一个没有原始调用过程信息的写回内核线程调用:

写入可以通过查看bio结构中的page引用推导出来 – 它具有struct address_space mapping 。 对应于打开的文件的struct file也包含指向同一个address_space实例的f_mapping ,它也指向包含文件名称的dentry (这可以通过使用task_dentry_path来完成)

所以我们需要两个探测器:一个捕获读取/写入文件的尝试,将路径和地址空间保存到关联数组中,其次捕获generic_make_request调用(这是由探测ioblock.request执行的)。

以下是一个计算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的信息,可以查看我的书: http : //myaut.github.io/dtrace-stap-book/kernel/async.html

也许iotop给你一个关于哪个进程正在做I / O的暗示,结果你有关于相关文件的想法。

 iotop --only 

–only选项用于仅查看正在执行I / O的进程或线程,而不显示所有进程或线程