public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* [Bug tapsets/17920] New: File descriptor to pathname function
@ 2015-02-03 18:25 brendan.d.gregg at gmail dot com
  2015-09-28 20:33 ` [Bug tapsets/17920] " dsmith at redhat dot com
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: brendan.d.gregg at gmail dot com @ 2015-02-03 18:25 UTC (permalink / raw)
  To: systemtap

https://sourceware.org/bugzilla/show_bug.cgi?id=17920

            Bug ID: 17920
           Summary: File descriptor to pathname function
           Product: systemtap
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: tapsets
          Assignee: systemtap at sourceware dot org
          Reporter: brendan.d.gregg at gmail dot com

FD to pathname translations are handy. Eg:

# ls -l /proc/1130/fd/1
l-wx------ 1 root root 64 Feb  3 18:21 /proc/1130/fd/1 ->
/mnt/logs/system/auth.log

I'd like a function in SystemTap that converts an integer file descriptor, for
the current process/task, to the pathname as seen by /proc/PID/fd. Without
needing kernel debuginfo (/proc/PID/fd doesn't need it).

The use case is identifying which file system files are being opened, read, and
written to. Other file descriptor types, like pipes and sockets, are less
important. I'd be fine with them returning just "[socket]" for now, or, better
still, just match what /proc already uses. Eg:

# ls -l /proc/18959/fd/3
lr-x------ 1 root root 64 Feb  3 18:20 /proc/18959/fd/3 -> socket:[181107359]

-- 
You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug tapsets/17920] File descriptor to pathname function
  2015-02-03 18:25 [Bug tapsets/17920] New: File descriptor to pathname function brendan.d.gregg at gmail dot com
@ 2015-09-28 20:33 ` dsmith at redhat dot com
  2015-09-29 14:45 ` dsmith at redhat dot com
  2015-10-02 17:06 ` dsmith at redhat dot com
  2 siblings, 0 replies; 4+ messages in thread
From: dsmith at redhat dot com @ 2015-09-28 20:33 UTC (permalink / raw)
  To: systemtap

https://sourceware.org/bugzilla/show_bug.cgi?id=17920

David Smith <dsmith at redhat dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dsmith at redhat dot com

--- Comment #1 from David Smith <dsmith at redhat dot com> ---
I looked into this today. I'm not sure it is possible to do, at least cleanly.

For reference's sake, here's what I came up with. Note that this only works on
semi-recent kernels (I developed this on rawhide -
4.3.0-0.rc2.git1.1.fc24.x86_64) and isn't correct with respect to locking data
structures. See comments for details.

====
function task_fd_lookup:long(task:long, fd:long)
%{
        struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task;
        unsigned int fd = (unsigned int)(unsigned long)STAP_ARG_fd;
        struct files_struct *files = NULL;
        struct file *file = NULL;
        int put_task_struct_needed = 0;

        /* Before using the task_struct pointer, make sure it is valid
         * to read. */
        (void)kderef_buffer(NULL, t, sizeof(struct task_struct));

        get_task_struct(t);
        put_task_struct_needed = 1;

        // This is *wrong*. We should be calling get_files_struct()
        // here, but it isn't exported. This means that we can't lock
        // the files_struct. So, let's hope keeping the task_struct
        // usage count increased is enough.
        files = t->files;

        if (files) {
                /* Before using the files_struct pointer, make sure it is
                 * valid to read. */
                (void)kderef_buffer(NULL, files, sizeof(struct files_struct));

                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                spin_unlock(&files->file_lock);
        }

        if (file) {
                // Sigh. This is really wrong also. We're returning a
                // pointer which isn't locked or has had its usage
                // count increased. There is nothing keeping this
                // pointer valid until we use it later.
                STAP_RETURN(file);
        }
        else {
            STAP_ERROR ("cannot find file in task");
        }

        CATCH_DEREF_FAULT();
        if (put_task_struct_needed)
                put_task_struct(t);
%}

probe begin
{
    file = task_fd_lookup(task_current(), 0)
    println(fullpath_struct_path(&@cast(file, "file")->f_path))
    exit()
}
====

Note that this code doesn't handle pipes, sockets, etc., but that is the least
of the worries about the above code.

Perhaps a better way of going here would be put a probe on vfs.open, vfs.write,
and vfs.read and if you aren't in your target process skip the probe. Something
like this:

====
probe vfs.read, vfs.write
{
    if (pid() != target()) next
    printf("%s: %s\n", name, fullpath_struct_path(&file->f_path))
}

probe vfs.open
{
    if (pid() != target()) next
    printf("%s: %s\n", name, pathname)
}
====

====
# stap ./file_monitor.stp -c "/bin/ls /dev/null"
/dev/null
vfs.open: /usr/bin/ls
vfs.read: /usr/bin/ls
vfs.read: /usr/bin/ls
vfs.read: /usr/bin/ls
vfs.open: /usr/lib64/ld-2.22.90.so
vfs.read: /usr/lib64/ld-2.22.90.so
vfs.read: /usr/lib64/ld-2.22.90.so
vfs.open: /etc/ld.so.cache
vfs.open: /usr/lib64/libselinux.so.1
vfs.read: /usr/lib64/libselinux.so.1
vfs.open: /usr/lib64/libcap.so.2.24
vfs.read: /usr/lib64/libcap.so.2.24
vfs.open: /usr/lib64/libc-2.22.90.so
vfs.read: /usr/lib64/libc-2.22.90.so
vfs.open: /usr/lib64/libpcre.so.1.2.5
vfs.read: /usr/lib64/libpcre.so.1.2.5
vfs.open: /usr/lib64/libdl-2.22.90.so
vfs.read: /usr/lib64/libdl-2.22.90.so
vfs.open: /usr/lib64/libattr.so.1.1.0
vfs.read: /usr/lib64/libattr.so.1.1.0
vfs.open: /usr/lib64/libpthread-2.22.90.so
vfs.read: /usr/lib64/libpthread-2.22.90.so
vfs.open: /usr/lib/locale/locale-archive
vfs.write: /dev/pts/2
====

-- 
You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug tapsets/17920] File descriptor to pathname function
  2015-02-03 18:25 [Bug tapsets/17920] New: File descriptor to pathname function brendan.d.gregg at gmail dot com
  2015-09-28 20:33 ` [Bug tapsets/17920] " dsmith at redhat dot com
@ 2015-09-29 14:45 ` dsmith at redhat dot com
  2015-10-02 17:06 ` dsmith at redhat dot com
  2 siblings, 0 replies; 4+ messages in thread
From: dsmith at redhat dot com @ 2015-09-29 14:45 UTC (permalink / raw)
  To: systemtap

https://sourceware.org/bugzilla/show_bug.cgi?id=17920

--- Comment #2 from David Smith <dsmith at redhat dot com> ---
I filed bug #19021 on the tapset function task_dentry_path(), asking that it
handle more than just files. That is the place to add support for sockets and
the like.

-- 
You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug tapsets/17920] File descriptor to pathname function
  2015-02-03 18:25 [Bug tapsets/17920] New: File descriptor to pathname function brendan.d.gregg at gmail dot com
  2015-09-28 20:33 ` [Bug tapsets/17920] " dsmith at redhat dot com
  2015-09-29 14:45 ` dsmith at redhat dot com
@ 2015-10-02 17:06 ` dsmith at redhat dot com
  2 siblings, 0 replies; 4+ messages in thread
From: dsmith at redhat dot com @ 2015-10-02 17:06 UTC (permalink / raw)
  To: systemtap

https://sourceware.org/bugzilla/show_bug.cgi?id=17920

David Smith <dsmith at redhat dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #3 from David Smith <dsmith at redhat dot com> ---
Fixed in commit 1ffc2a8. Frank convinced me that I was being too pessimistic
about my original code.

Here's an example of how you call the new task_fd_lookup() function:

====
    try {
         file = task_fd_lookup(task_current(), 5)
         printf("%d: %s\n", 5, fullpath_struct_file(task_current(), file))
    } catch {
         printf("%d: fail reading file\n", 5)
    }
====

Also bug #9021 is now fixed, so task_dentry_path() should return the correct
pathnames for synthetic filesystems, like pipes, sockets, etc.

-- 
You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-10-02 17:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-03 18:25 [Bug tapsets/17920] New: File descriptor to pathname function brendan.d.gregg at gmail dot com
2015-09-28 20:33 ` [Bug tapsets/17920] " dsmith at redhat dot com
2015-09-29 14:45 ` dsmith at redhat dot com
2015-10-02 17:06 ` dsmith at redhat dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).