Exercise 2

We will have to use count() aggregation to count open() and openat() system calls. It can be cleaned up from outdated data with trunc() action in DTrace or delete operation in SystemTap. These scripts are roughly based on wstat.d and wstat.stp from aggregations example.

To print current timestamp we can use %Y formatting specifier and walltimestamp variable in DTrace. Same can be achieved with ctime() and gettimeofday_s() functions from SystemTap. To print data periodically, we can use timer probes: timer.s($1) in SystemTap or tick-$1s from DTrace. $1 here represents first command line argument.

Finally, we need to determine if open operation requests creation of file or not. We should write predicate for that which tests flags passed to open for O_CREAT flag (we have learned how to access flags in previous exercise).

Here are resulting scripts:

  Script file openaggr.d

/(arg2 & O_CREAT) == O_CREAT/ {
    @create[execname, pid] = count();

/(arg2 & O_CREAT) == 0/ {
    @open[execname, pid] = count();

/ arg1 > 0 / {
    @success[execname, pid] = count();

tick-$1s {
    printf("%Y\n", walltimestamp);
    printf("%12s %6s %6s %6s %s\n", 
              "EXECNAME", "PID", "CREATE", "OPEN", "SUCCESS");
    printa("%12s %6d %@6d %@6d %@d\n", @create, @open, @success);
    trunc(@create); trunc(@open); trunc(@success);

  Script file openaggr.stp

global open, creat, success
global O_CREAT = 64;

probe syscall.open {
    if(flags & O_CREAT)
        creat[execname(), pid()] <<< 1;
        open[execname(), pid()] <<< 1;

probe syscall.open.return {
    if($return >= 0)
        success[execname(), pid()] <<< 1;

probe timer.s($1) {
    printf("%12s %6s %6s %6s %s\n", 
           "EXECNAME", "PID", "CREATE", "OPEN", "SUCCESS");
    foreach([en, pid+] in open) {
        printf("%12s %6d %6d %6d %d\n", 
               en, pid, @count(creat[en, pid]), @count(open[en, pid]),
               @count(success[en, pid]));

    delete open; delete creat; delete success;