This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: How to get write/read offset?


On Fri, Mar 11, 2016 at 3:52 PM, David Smith <dsmith@redhat.com> wrote:
> 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.
>
To bad, this function is implemented in SystemTap as of 2.9 when I am
not mistaken and I am on CentOS 7 with SystemTap 2.8.
I might give it a try to compile 2.9 or 3.0 on CentoOS 7

>> 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?
>
I get the name "urandom" from $file for the probes vfs.{read|write}
But that still does not explain why the name is empty on that fop
probe.
But it is not a big issue.


>> 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.

There seem to be many ways to get what one wants :) I found that one:
filename = __file_filename(file)

Is there somewhere a documentation of those helpers like __file_filename etc?

Thanks a lot,
Bjoern


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]