This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: How to get write/read offset?
- From: "Olausson, Bjoern" <contactme at olausson dot de>
- To: David Smith <dsmith at redhat dot com>
- Cc: systemtap at sourceware dot org
- Date: Fri, 11 Mar 2016 16:35:09 +0100
- 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> <56E2DB9D dot 5080901 at redhat dot com>
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