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: dereferencing filenames from a vfs_write probe


On Thu, Mar 20, 2008 at 12:17:58PM +0800, Eugene Teo wrote:
> Hi Dave,
> 
> <quote sender="dave-systemtap@skeptech.org">
> > So, I'm looking at some of the existing code on the wiki
> > and the internet at large which probes vfs_(read|write) for various
> > things.  For my purpose, it'd be handy to get a filename back from the
> > probe instead of (or in addition to) an inode number.  
> > 
> > for example:
> > 
> > probe kernel.function ("vfs_write"),
> >       kernel.function ("vfs_read")
> > {
> >   fname = $file->f_dentry-> <something>
> > 
> >    printf ("%s(%d,%d) %s\n",
> >      execname(), pid(), uid(), fname)
> > }
> 
> It would be useful if you also include the kernel version, as structures
> may change in between versions.

This happens to be 2.6.16.19.  I'm curious, how often do systemtap
scripts need to change in practice because of data struture changes in
the kernel? 

> 
> linux-2.6:
>  779 struct file {
> [...]
>  788         struct path             f_path;
>  789 #define f_dentry        f_path.dentry
>  790 #define f_vfsmnt        f_path.mnt
> 
> It is possible to get hold of the path name (including the filename)
> using d_path().
> 
> I have not tested it, but I have a piece of code I used in a script
> elsewhere that you can probably amend and reuse:
> 
> function get_d_path_info:string (task:long, fd:long) %{
> 	struct task_struct *p = (struct task_struct
> *)((long)THIS->task);
> 	struct files_struct *files = kread(&p->files);
> 	char *page = (char *)__get_free_page(GFP_KERNEL);
> 	struct file *filp;
> 	struct dentry *dentry;
> 	struct vfsmount *vfsmnt;
> 
> 	spin_lock(&files->file_lock);
> 	filp = fcheck_files(files, THIS->fd);
> 	dentry = kread(&filp->f_path.dentry);
> 	vfsmnt = kread(&filp->f_path.mnt);
> 	snprintf(THIS->__retvalue, MAXSTRINGLEN, "      %s",
> 			d_path(dentry, vfsmnt, page, PAGE_SIZE));
> 	free_page((unsigned long)page);
> 	spin_unlock(&files->file_lock);
> 	CATCH_DEREF_FAULT();
> %}

Cool thanks. So based on that code I've chopped out the following function:

function get_path:string (dentry:dentry *,vsmnt:vsmount *) %{
  char *page = (char *)__get_free_page(GFP_KERNEL);
  sprintf("%s",d_path(dentry, vfsmnt, page, PAGE_SIZE));
  free_page((unsigned long)page);
%}

and am attempting to pass pointers to the requisite structs like so:
path=get_path($file->f_dentry, $file->f_vfsmnt)

This is, as you probably guessed, giving me a parse error: 

parse error: expected 'string' or 'long'
        
I guess this means I'm only allowed to pass strings or longs into
embedded C functions. I guess it's time to do some more rtfm'ing. 

parent=kernel_string($file->pathsearch) works perfectly btw. 

Thanks

--dave
 
> Thanks,
> Eugene

Attachment: pgp00000.pgp
Description: PGP signature


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