Monday, 15 October 2012

DTrace update

Havent really touched dtrace in a while - bar some minor bug

Claudio K. sent me an interesting mail and was questioning why this
didnt work:

# dtrace -n 'syscall:::entry {
self->start = timestamp;
self->file = fds[arg0].fi_pathname;
syscall:::return/(timestamp - self->start) > 1073741824/
printf("%d ns on %s", timestamp - self->start, self->file);
self->start = 0;
' -p 26544

I briefly glanced the command, noted the use of "-p" and assumed this
was the problem. Claudio highlighted the 3rd line
referring to the fds[] array
and I was scratching my head wondering what was going on here. The
code makes sense, but I was trying to figure out how this actually worked.

Research showed this is handled by this, in etc/io.d:

inline fileinfo_t fds[int fd] = xlate (
fd >= 0 && fd < curthread->t_procp->p_user.u_finfo.fi_nfiles ?
curthread->t_procp->p_user.u_finfo.fi_list[fd].uf_file : NULL);

Now this was commented out in etc/io.d a long time back, by me,
because I was never ready for it. Those structures are Solaris

An excellent posting by the author is available here on translators:

So far, so good. So I started converting this to Linux structures and
apart from a minor issue in the libdtrace code (to do with ctf access
to the kernel structures), its not far off:

$ dtrace -n syscall::open:'{printf("%p", fds[arg0].fi_offset);}'

So, open, arg0 is a string, and we want the filename. The
nice thing about these translators is that they are a recipe for
accessing struct-like members without having to precreate the
return value for all elements of the structure. (I had fallen foul
of this in existing driver code - and can start to discard the horrible

But the *filename*. Well, Solaris has access to this. Linux has
access to the filename (but - I need to do some homework, because Linux
has access via a function, and dtrace wont let us do that at the moment).
But on *MacOS*, its interesting because they simply did not bother.

translator fileinfo_t < struct fileglob *F > {
fi_name = (F == NULL) ? "<none>" :
F->fg_type == DTYPE_VNODE ?
((struct vnode *)F->fg_data)->v_name == NULL ? "<unknown>" :
F->fg_type == DTYPE_SOCKET ? "<socket>" :

Example from MacOS:

dtrace -n syscall::open:entry'{printf("%s", fds[arg0].fi_name);}'

dtrace: description 'syscall::open:entry' matched 1 probe

1 18659 open:entry <none>
1 18659 open:entry <none>
0 18659 open:entry <none>

If you try to access the filename of a file descriptor on MacOS, you
get an "unknown" output (or "socket", etc). You cannot gain access to the
filename - they just havent implemented that facility. Which is a shame,
as it is mightily powerful.

On Linux, despite a function being available in the kernel to
convert a file to a name, it is a mutex/blocking function, so we
cannot call it directly, and may need a private implementation
without blocking semantics (occasionally, this could lead to output
corruption, but that should be rare for the scenarios we are normally
interested in).

I'll spend some time seeing if I can get something to work in this
area, and I will have usefully learnt something whilst adding a new
valuable feature to DTrace (or rather, got a facility working as it should

Post created by CRiSP v11.0.12a-b6455

No comments:

Post a Comment