Skip to content

Instantly share code, notes, and snippets.

@Martiusweb
Created April 14, 2014 09:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Martiusweb/10633360 to your computer and use it in GitHub Desktop.
Save Martiusweb/10633360 to your computer and use it in GitHub Desktop.
Monitor some IO operations on Linux
#!/usr/bin/env stap
/* Usage:
* monitor_io.stp (data|metadata|all) [with_lookup]
*
* - data: monitor reads/writes (currently, reads only)
* - metadata: monitor metadata reads/writes
* - all: monitor both
*/
function is_block_device:long(dentry:long) {
superblock = @cast(dentry, "struct dentry")->d_sb;
return @cast(superblock, "struct super_block")->s_bdev;
}
function log(message:string) {
printf("%s\t%s\n", ctime(gettimeofday_s()), message);
}
probe begin {
printf("Begin monitoring (data? metadata? %s)\n", @1);
}
%($# > 1 %?
%(@1 == "metadata" || @1 == "all" && @2 == "with_lookup" %?
/* First, monitor metadata reads
* lookup_real is called when the VFS asks the underlying filesystem to
* lookup for the inode matching a given path.
* It does not exactly mean "read on the disk", since the FS can hold
* its own cache (ex: XFS), but it is still a good approximation.
*/
probe kernel.function("lookup_real") {
if(is_block_device($dentry)) { /* associated to an actual block device */
log(sprintf("lookup for: %s", reverse_path_walk($dentry)));
}
}
%)
%)
%(@1 == "metadata" || @1 == "all" %?
/* Monitor metadata writes:
* For any inode operation, there is a higher-level "vfs_[op]" function.
* Of course, there is an exception: for setattr, we watch notify_change
*/
probe kernel.function("vfs_link") {
if(is_block_device($old_dentry)) {
log(sprintf("create link: %s (points to %s)",
reverse_path_walk($new_dentry),
reverse_path_walk($old_dentry)
));
}
}
probe kernel.function("vfs_unlink") {
if(is_block_device($dentry)) {
log(sprintf("unlink: %s",
reverse_path_walk($dentry)
));
}
}
probe kernel.function("vfs_symlink") {
if(is_block_device($dentry)) {
log(sprintf("create symlink: %s (points to \"%s\")",
reverse_path_walk($dentry),
kernel_string($oldname)
));
}
}
probe kernel.function("vfs_mkdir") {
if(is_block_device($dentry)) {
log(sprintf("create directroy: %s",
reverse_path_walk($dentry)
));
}
}
probe kernel.function("vfs_rmdir") {
if(is_block_device($dentry)) {
log(sprintf("remove directroy: %s",
reverse_path_walk($dentry)
));
}
}
probe kernel.function("vfs_rename") {
if(is_block_device($old_dentry) || is_block_device($new_dentry)) {
log(sprintf("rename: %s in %s",
reverse_path_walk($old_dentry),
reverse_path_walk($new_dentry)
));
}
}
probe kernel.function("vfs_setxattr") {
if(is_block_device($dentry)) {
log(sprintf("set extended attribute: %s",
reverse_path_walk($dentry)
));
}
}
probe kernel.function("vfs_removexattr") {
if(is_block_device($dentry)) {
log(sprintf("set extended attribute: %s",
reverse_path_walk($dentry)
));
}
}
probe kernel.function("notify_change") {
if(is_block_device($dentry)) {
log(sprintf("set attribute: %s",
reverse_path_walk($dentry)
));
}
}
%)
%(@1 == "data" || @1 == "all" %?
global file_path;
/* Now, we monitor page pulled from disc, based on the technique from:
* http://glandium.org/blog/?p=1476
*/
probe kernel.function("__do_page_cache_readahead") {
file_path[tid()] = reverse_path_walk($filp->f_path->dentry);
}
probe kernel.function("do_mpage_readpage") {
if(tid() in file_path) {
log(sprintf("read block of %s (offset: %d)",
file_path[tid()],
$page->index*4096
));
}
}
probe kernel.function("__do_page_cache_readahead").return {
delete file_path[tid()];
}
/* TODO writes */
%)
probe end {
print("End monitoring\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment