This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: How to get write/read offset?
- From: David Smith <dsmith at redhat dot com>
- To: "Olausson, Bjoern" <contactme at olausson dot de>
- Cc: systemtap at sourceware dot org
- Date: Fri, 11 Mar 2016 08:52:13 -0600
- Subject: Re: How to get write/read offset?
- Authentication-results: sourceware.org; auth=none
- References: <CAE7O3Tc5T8UfZgJegQ8H6mZ7r+fd+kSMtPUd9EmLvVS=S2ZyVQ at mail dot gmail dot com> <56E1C72B dot 1080402 at redhat dot com> <CAE7O3TcWYCkBPZO5JMLN7U7fDV9x634Qt2nx7kX_doS-32kLyw at mail dot gmail dot com>
On 03/10/2016 05:59 PM, Olausson, Bjoern wrote:
> On Thu, Mar 10, 2016 at 8:12 PM, David Smith <dsmith@redhat.com> wrote:
>> On 03/10/2016 06:32 AM, Olausson, Bjoern wrote:
>>> Hello Systemtap users,
>>>
>>> is there some straight forward way to get the offset for any read,
>>> write, pwrite etc. syscall?
>>>
>>> So for example if I trace the the IO to a file and the program issues
>>> a "seek" and writes reads n bytes starting from this position, is
>>> there any way to get that start position (offset) except from probing
>>> for an "seek" before a write/read?
>>>
>>> For example:
>>>
>>> probe syscall.write.return {
>>> if (pid() == target()) {
>>> time_stamp = timestamp()
>>> p = pid()
>>> fd = $fd
>>> bytes = $return
>>> latency = gettimeofday_us() - @entry(gettimeofday_us())
>>> printf("%d;%d;%s;%s;%d;%d;%d\n", p, fd, filehandles[p, fd], name,
>>> bytes, time_stamp, latency)
>>> }
>>> }
>>>
>>> If there is no straight forward way to get this information, what is
>>> the most native way to get the offset alongside with the time, latency
>>> and bytes_written/read?
>>
>> To get the file offset, you'll have to probe 1 level down. syscall.read
>> (sys_read()) is basically a wrapper around vfs.read (vfs_read()).
>> syscall.write (sys_write()) is basically a wrapper around vfs.write
>> (vfs_write()).
>>
>> So, you can (almost) replace syscall.write.return in your example above
>> with vfs.write.return. One of the differences are that you don't get $fd
>> anymore, instead you get a 'struct file' pointer.
>>
>>
>> --
>> David Smith
>> dsmith@redhat.com
>> Red Hat
>> http://www.redhat.com
>> 256.217.0141 (direct)
>> 256.837.0057 (fax)
>
> Hello David,
>
> thanks for the quick answer!
>
> So far I managed to get what I want:
> --------------------------------------------------
> global start
> global filehandles
>
> function timestamp:long() { return gettimeofday_us() - start }
>
> probe begin {
> start = gettimeofday_us()
> printf("File Name;Syscall;Timestamp;Latency;Offset;Bytes to
> write/read;Bytes written/read;Bytes\n")
> }
>
> probe generic.fop.open {
> if (pid() == target()) {
> filehandles[ino] = filename
> }
> }
>
> probe vfs.write.return {
> if (pid() == target()) {
> time_stamp = timestamp()
> latency = gettimeofday_us() - @entry(gettimeofday_us())
> #printf("%s\n", $$parms$$)
> offset = $file->f_pos
> filename = filehandles[ino]
> bytes = $return
> printf("%s;%s;%d;%d;%d;%d;%d;%d\n", filename, name,
> time_stamp, latency, offset, bytes_to_write, bytes_written, bytes)
> }
> }
>
> probe vfs.read.return {
> if (pid() == target()) {
> time_stamp = timestamp()
> latency = gettimeofday_us() - @entry(gettimeofday_us())
> offset = $file->f_pos
> filename = filehandles[ino]
> bytes = $return
> printf("%s;%s;%d;%d;%d;%d;%d;%d\n", filename, name,
> time_stamp, latency, offset, bytes_to_read, bytes_read, bytes)
> }
> }
>
> #probe generic.fop.llseek.return {
> # if (pid() == target()) {
> # time_stamp = timestamp()
> # latency = gettimeofday_us() - @entry(gettimeofday_us())
> # ino = $file->
> # filename = filehandles[ino]
> # printf("%s;%s;%d;%d;%d;%d;%d;%d\n", filename, name,
> time_stamp, latency, offset)
> # }
> #}
> --------------------------------------------------
>
> I have three questions:
>
> 1)
> How to get the inode info when I probe for a llseek to map it to a
> human readable filename.
In vfs.read, vfs.write, and generic.fop.lseek, you've got $file, which
is 'struct file' pointer. You can call the following:
fullpath_struct_file(task_current(), $file)
to get the full path for $file. That should simplify your script a bit
since you won't need the filehandles cache anymore.
> 2)
> When I read from e.g. /dev/urandom, "filename" in "generic.fop.open"
> is empty ("")
Hmm, I'm not sure on this one. Perhaps because that on a synthetic
filesystem?
> 3)
> Is there a direct way to get the filename from the array $file within
> vfs.{read|write|llseek}.return (I couldn't find it) so I can omit the
> mapping?
See above.
--
David Smith
dsmith@redhat.com
Red Hat
http://www.redhat.com
256.217.0141 (direct)
256.837.0057 (fax)