Created
December 9, 2010 20:29
-
-
Save erickt/735283 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| function __task_file_handle_filp:long(task:long, fd:long) %{ /* pure */ | |
| struct task_struct *p = (struct task_struct *)((long)THIS->task); | |
| struct files_struct *files; | |
| struct file *filp; | |
| rcu_read_lock(); | |
| if ((files = kread(&p->files))) { | |
| if ((filp = fcheck_files(files, THIS->fd))) { | |
| THIS->__retvalue = (long)filp; | |
| } | |
| } | |
| CATCH_DEREF_FAULT(); | |
| rcu_read_unlock(); | |
| %} | |
| function __task_dentry_prepend:string(dentry:long,name:string) | |
| { | |
| dname = d_name(dentry) | |
| /* | |
| * In case we are following down a mount point trigger, we can get | |
| * multiple instances of a root mount. | |
| */ | |
| c = substr(name, strlen(name)-1, strlen(name)-1) | |
| if (dname == "/" && c == "/") | |
| return name | |
| if (name == "") { | |
| return dname; | |
| } else { | |
| return sprintf("%s/%s", dname, name) | |
| } | |
| } | |
| /** | |
| * sfunction task_dentry_path - get the full dentry path | |
| * | |
| * Returns the full dirent name (full path to the root), like | |
| * the kernel d_path function. | |
| * @task: task_struct pointer. | |
| * @dentry: direntry pointer. | |
| * @vfsmnt: vfsmnt pointer. | |
| */ | |
| function __task_dentry_path(task:long, dentry:long, vfsmnt:long) | |
| { | |
| root = & @cast(task, "task_struct")->fs->root | |
| while (1) { | |
| if (dentry == @cast(root, "path")->dentry && | |
| vfsmnt == @cast(root, "path")->mnt) | |
| break; | |
| if (dentry == @cast(vfsmnt, "vfsmount")->mnt_root || | |
| __dentry_IS_ROOT(dentry)) { | |
| /* Global root? */ | |
| if (@cast(vfsmnt, "vfsmount")->mnt_parent == vfsmnt) { | |
| return sprintf("/%s", name) | |
| } | |
| dentry = @cast(vfsmnt, "vfsmount")->mnt_mountpoint | |
| vfsmnt = @cast(vfsmnt, "vfsmount")->mnt_parent | |
| continue | |
| } | |
| name = __task_dentry_prepend(dentry, name) | |
| dentry = @cast(dentry, "dentry")->d_parent | |
| } | |
| return sprintf("/%s", name) | |
| } | |
| /** | |
| * sfunction task_file_handle_path - get the full path of a file descriptor | |
| * | |
| * Returns the full dirent name (full path to the root), like the kernel d_path function. | |
| * @task: task_struct pointer. | |
| * @fd: file descriptor. | |
| */ | |
| function task_file_handle_path:string(task:long, fd:long) | |
| { | |
| filp = __task_file_handle_filp(task, fd) | |
| if (!filp) { | |
| return "" | |
| } | |
| dentry = (@defined(@cast(filp,"file")->f_path->dentry) | |
| ? @cast(filp,"file")->f_path->dentry | |
| : @cast(filp,"file")->f_dentry) | |
| vfsmnt = (@defined(@cast(filp,"file")->f_path->mnt) | |
| ? @cast(filp,"file")->f_path->mnt | |
| : @cast(filp,"file")->f_vfsmnt) | |
| return __task_dentry_path(task, dentry, vfsmnt) | |
| } | |
| global openedFileActiveTime = $1 | |
| global openedFileSleepTime = $2 | |
| global openedFileEnabled = 0 | |
| global openedFileSampleTime = 0 | |
| global fileIOActiveTime = $3 | |
| global fileIOSleepTime = $4 | |
| global fileIOEnabled = 0 | |
| global fileIOSampleTime = 0 | |
| global files, iostats, deltas | |
| # Look up the file. | |
| function find_file_path(task, p, fd) | |
| { | |
| file = files[p, fd] | |
| if (file == "") { | |
| file = task_file_handle_path(task, fd) | |
| } | |
| return file | |
| } | |
| # Log the io traffic. | |
| function report_io(pid, fd, syscall, tstamp, file) | |
| { | |
| count = @count(iostats[pid, fd, syscall]) | |
| if (count > 0) { | |
| minsample = @min(iostats[pid, fd, syscall]) | |
| maxsample = @max(iostats[pid, fd, syscall]) | |
| total = @sum(iostats[pid, fd, syscall]) | |
| printf("io:%d:%d:%d:%d:%d:%d:%d:%s\n", | |
| tstamp, pid, | |
| syscall, minsample, maxsample, count, total, file) | |
| } | |
| } | |
| # Save the file when a file gets opened. | |
| probe kernel.function("sys_open").return | |
| { | |
| if ($return >= 0) { | |
| p = pid() | |
| task = task_current() | |
| # Save the filename in a cache. | |
| file = task_file_handle_path(task, $return) | |
| if (file != "") { | |
| files[p, $return] = file | |
| if (openedFileEnabled) { | |
| printf("file:%d:%d:%s\n", gettimeofday_ns(), p, file) | |
| } | |
| } | |
| } | |
| } | |
| # If a file gets closed, report those statistics right away. | |
| probe kernel.function("sys_close") | |
| { | |
| p = pid() | |
| task = task_current() | |
| # Look up the filename in a cache. | |
| file = find_file_path(task, p, $fd) | |
| # If we found a file, report it. | |
| if (file != "") { | |
| tstamp = gettimeofday_ns() | |
| report_io(p, $fd, 0, tstamp, file) | |
| report_io(p, $fd, 1, tstamp, file) | |
| report_io(p, $fd, 2, tstamp, file) | |
| } | |
| # Clean up our caches. | |
| delete iostats[p, $fd, 0] | |
| delete iostats[p, $fd, 1] | |
| delete iostats[p, $fd, 2] | |
| delete files[p, $fd] | |
| } | |
| # Record all the read iowait time and their traffic. | |
| probe kernel.function("sys_read") if (fileIOEnabled) | |
| { | |
| deltas[tid(), 1] = gettimeofday_ns() | |
| } | |
| probe kernel.function("sys_read").return.maxactive(20) if (fileIOEnabled) | |
| { | |
| t = tid() | |
| starttime = deltas[t, 1] | |
| delete deltas[t, 1] | |
| # We ignore a return of 0 bytes because that means we are at the end of the | |
| # file. | |
| if ($return > 0) { | |
| p = pid() | |
| # Save that this fd has data. | |
| if (starttime != 0) { | |
| iostats[p, $fd, 0] <<< gettimeofday_ns() - starttime | |
| } | |
| iostats[p, $fd, 1] <<< $return | |
| } | |
| } | |
| # Record all the write iowait time and their traffic. | |
| probe kernel.function("sys_write") if (fileIOEnabled) | |
| { | |
| deltas[tid(), 2] = gettimeofday_ns() | |
| } | |
| probe kernel.function("sys_write").return.maxactive(20) if (fileIOEnabled) | |
| { | |
| t = tid() | |
| starttime = deltas[t, 2] | |
| delete deltas[t, 2] | |
| if ($return >= 0) { | |
| p = pid() | |
| # Save that this fd has data. | |
| if (starttime != 0) { | |
| iostats[p, $fd, 0] <<< gettimeofday_ns() - starttime | |
| } | |
| iostats[p, $fd, 2] <<< $return | |
| } | |
| } | |
| # Report all the statistics and clear the caches. | |
| function report_all_stats(tstamp) | |
| { | |
| foreach ([p, fd, syscall] in iostats) { | |
| file = files[p, fd] | |
| if (file != "") { | |
| task = pid2task(p) | |
| if (task) { | |
| file = find_file_path(task, p, fd) | |
| } | |
| } | |
| if (file != "") { | |
| files[p, fd] = file | |
| report_io(p, fd, 0, tstamp, file) | |
| report_io(p, fd, 1, tstamp, file) | |
| report_io(p, fd, 2, tstamp, file) | |
| } | |
| } | |
| # Clean up all the io stat caches. | |
| delete iostats | |
| } | |
| # Cycle whether or not we are gathering statistics. | |
| probe timer.s(1) if (openedFileSleepTime != 0 || fileIOSleepTime != 0) | |
| { | |
| tstamp = gettimeofday_ns() | |
| tstamp_s = tstamp / 1000000000 | |
| report_all_stats(tstamp) | |
| # Toggle tracking opened files. | |
| if (openedFileSleepTime != 0) { | |
| if (openedFileEnabled) { | |
| if (tstamp_s - openedFileSampleTime > openedFileActiveTime) { | |
| openedFileEnabled = 0 | |
| openedFileSampleTime = tstamp_s | |
| } | |
| } else { | |
| if (tstamp_s - openedFileSampleTime > openedFileSleepTime) { | |
| openedFileEnabled = 1 | |
| openedFileSampleTime = tstamp_s | |
| } | |
| } | |
| } | |
| # Toggle tracking file io. | |
| if (fileIOSleepTime != 0) { | |
| if (fileIOEnabled) { | |
| if (tstamp_s - fileIOSampleTime > fileIOActiveTime) { | |
| fileIOEnabled = 0 | |
| fileIOSampleTime = tstamp_s | |
| } | |
| } else { | |
| if (tstamp_s - fileIOSampleTime > fileIOSleepTime) { | |
| fileIOEnabled = 1 | |
| fileIOSampleTime = tstamp_s | |
| } | |
| } | |
| } | |
| } | |
| # Clear the file cache every 30 seconds. | |
| probe timer.s(30) | |
| { | |
| delete files | |
| } | |
| probe begin | |
| { | |
| openedFileEnabled = openedFileActiveTime != 0 | |
| fileIOEnabled = fileIOActiveTime != 0 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment