Created
April 14, 2014 09:50
-
-
Save Martiusweb/10633360 to your computer and use it in GitHub Desktop.
Monitor some IO operations on Linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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