Alan Hargreaves' Blog

The ramblings of an Australian SaND TSC* Principal Field Technologist

More DTrace Lab Answers

OK, I promised more answers so here we go, … (sorry, where files have copyright notices, I have to leave them there).

Exercise 2

Restrict the iosnoop.d to trace a specific process.

This solution will allow you to either specify a pid by appending ‘-p {pid}’ or to run a command by appending ‘-c “command args …” to the command line. eg dtrace -s iosnoop.d -p 1234

* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License").  You may not use this file except in compliance
* with the License.
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or
* See the License for the specific language governing permissions
* and limitations under the License.
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
* Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
* Use is subject to license terms.
* This D script is used as an example in the Solaris Dynamic Tracing Guide
* wiki in the "io Provider" Chapter.
* The full text of the this chapter may be found here:
* On machines that have DTrace installed, this script is available as
* iosnoop.d in /usr/demo/dtrace, a directory that contains all D scripts
* used in the Solaris Dynamic Tracing Guide.  A table of the scripts and their
* corresponding chapters may be found here:
*   file:///usr/demo/dtrace/index.html
#pragma D option quiet
printf("%10s %58s %2s\n", "DEVICE", "FILE", "RW");
/pid == $target/
printf("%10s %58s %2s\n", args[1]->dev_statname,
args[2]->fi_pathname, args[0]->b_flags & B_READ ? "R" : "W");

Exercise 3

Display the arguments for the rename(2) system call along with its return code.

This is longer than it needs to be as I like the idea of a single line of output for each time the we have a rename() system call. I save the two arguments in thread local variables (self->source and self->destination). Note that the two arguments are strings and they are in user space when this probe fires, so we use copyinstr() to both get them into kernel context and make them printable strings. Note also that we clean up after ourselves in the return probe.

#!/usr/sbin/dtrace -s
#pragma D option quiet
syscall::rename:entry {
self->source = copyinstr(arg0);
self->destination = copyinstr(arg1);
syscall::rename:return {
printf("%s: %s -> %s returned %d\n", probefunc, self->source,
self->destination, arg1);
self->source = self->destination = 0;

Exercise 4

Display the real and sys times (see timex(1)) for the syscall

I’m not completely happy with this as I saw some anomalous real time values running this on my notebook, but it should be about right. Note that we record a walltimestamp (seconds since epoch) and the vtimestamp (time on cpu in nanoseconds) and simply compare them in the return probe.

#!/usr/sbin/dtrace -s
#pragma D option quiet
syscall:::entry {
self->seconds = walltimestamp;
self->sys = vtimestamp;
syscall:::return /self->sys/ {
printf("%s: %d real seconds, %dns system\n",
walltimestamp - self->seconds,
vtimestamp - self->sys);
self->seconds = self->sys = 0;

Exercise 5

Show the kernel function name that triggers the io:::start probe.

Many folks did this using stack(). There is a better way. This makes use of the fact that in the io provider, the probe* values are defined.

$ pfexec dtrace -qn 'io:::start {printf("iostart:::probefunc called from %s\n",probefunc);}'
iostart:::probefunc called from bdev_strategy

You could also simply use the default action without -q as that will print the probe specification each time it fires, which will include the probefunc.

Exercise 6

Show the flow of kernel functions for a write system call.

Most folks put a -F in the arguments on line 1. The clearer (and more correct) way to do this in a script is to use the pragma (highlighted).

#!/usr/sbin/dtrace -s
#pragma D option flowindent
syscall::write:entry { self->interest = 1; }
fbt::: /self->interest/ {}
syscall::write:return { self->interest = 0; }

Exercise 7

Show all lock events for mutexes that occur during two second.

The question hints that we may want to use an aggregation and summary rather than printing them as they happen.

#!/usr/sbin/dtrace -s3
#pragma D option quiet
lockstat:::adaptive* {@[probename] = count();}
tick-2s {exit(0);}

Exercise 8

Find file to which most IO is being done.

I’m going to assume that the question means real IO, not IOs that hit the cache. In which case, we can use the answer to exercise 2 as a hint. Unfortunately, pretty much all of the IO that this tracks is being done by sched to flush buffers and we don’t have any idea of the filename. I’ll try to come up with a better solution.

#!/usr/sbin/dtrace -s
#pragma D option quiet
BEGIN { printf("Collecting data ... ^C to finish.\n"); }
io:::start { @[args[2]->fi_pathname] = count(); }
END { trunc(@,1); printa(@); }

That’s it for the moment, I’ll finish them off later.


Written by Alan

November 14, 2008 at 9:55 pm

Posted in Solaris

One Response

Subscribe to comments with RSS.

  1. Alan,
    Thanks… It’s very instructive to see the solutions to some of these puzzlers.


    November 15, 2008 at 2:25 pm

Comments are closed.

%d bloggers like this: