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?


Perfect!

Thanks a lot!

On Fri, Mar 11, 2016 at 5:59 PM, David Smith <dsmith@redhat.com> wrote:
> On 03/11/2016 09:35 AM, Olausson, Bjoern wrote:
>> 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
>
> Ah, sorry. You should be able to write fullpath_struct_file() yourself.
> It is just a wrapper around task_dentry_path(), which should already be
> in 2.8. So, just steal the definition from the following link and add it
> to your script.
>
> <https://www.sourceware.org/git/gitweb.cgi?p=systemtap.git;a=blob;f=tapset/linux/dentry.stp;h=061876736abd6c56a55afb46442ef54c0b16f06c;hb=HEAD>
>
>
>>>> 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?
>
> No, not really. Anything that starts with '__' is meant to be an
> internal function or variable.
>
> --
> David Smith
> dsmith@redhat.com
> Red Hat
> http://www.redhat.com
> 256.217.0141 (direct)
> 256.837.0057 (fax)


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