Linux NFS development
 help / color / mirror / Atom feed
From: Xue Peng Li <xuepengl@cn.ibm.com>
To: "systemtap@sourceware.org" <systemtap@sourceware.org>,
	        nfs@lists.sourceforge.net
Subject: Re: [ltc-perf]  draft of nfs event hook
Date: Fri, 11 Aug 2006 09:57:29 +0800	[thread overview]
Message-ID: <44DBE409.4080907@cn.ibm.com> (raw)
In-Reply-To: <44C8C631.40003@cn.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 8383 bytes --]

Hi folks,

    I am working on NFS tapsets recently which could be able to probe 
both NFS server side and client side operations. As the first step, I am 
working on tapsets about NFS client side. This tapset includes three 
levels, i.e. file operation, address space operation, client-side 
procedures stubs(nfs_proc function). I have finished the tapset about 
fop(file operation) and aop (address space operation). I resues the 
Tom's vfs.stp to avoid duplicate work.

    I will be very happy if you can take a look at it. Feel free to tell 
me if you have any questions/suggestions/comments.

    Thanks.

Li Guanglei wrote:
> Hi,
> 
>   The NFS trace hooks we are working on will be part of the trace hooks 
> of LKET, which is a system trace tool and we mainly use it for 
> performance analysis.
> 
>   LKET is a dynamic trace facility based on SystemTap. It is actually 
> implemented as SystemTap's tapsets library and it has been integrated 
> into SystemTap already. For more info of LKET, you can refer to:
> 
> http://sourceware.org/systemtap/man5/lket.5.html
> 
>   When we started working on NFS trace hooks, we realized it is not an 
> easy task. Although we use NFS in daily work but we don't have much 
> knowledge about the NFS protocol details and its implementation inside 
> the Kernel. So I divided the work into two steps. At the first step I 
> need get a list of trace points. And at the second step I need to make 
> sure what trace data is available for each trace hook. In a short, the 
> trace data available for each hook will be derived from the arguments of 
> the kernel functions being probed.
> 
>   We read through the Kernel source code and chose some functions to be 
> instrumented. We will trace the entry of these functions and if 
> necessary, the return of them will also be traced. The following is the 
> list of these functions, please take a review:
> 
> ==================== Client Side ==========================
> 
> <1> nfs directory operations
> 
>      All functions from nfs_dir_operations:
> 
>       const struct file_operations nfs_dir_operations = {
>         .llseek         = nfs_llseek_dir,
>         .read           = generic_read_dir,
>         .readdir        = nfs_readdir,
>         .open           = nfs_opendir,
>         .release        = nfs_release,
>         .fsync          = nfs_fsync_dir,
> };
> 
> <2> nfs file operations
> 
>     All functions from nfs_file_operations:
> 
>     const struct file_operations nfs_file_operations = {
>         .llseek         = nfs_file_llseek,
>         .read           = do_sync_read,
>         .write          = do_sync_write,
>         .aio_read               = nfs_file_read,
>         .aio_write              = nfs_file_write,
>         .mmap           = nfs_file_mmap,
>         .open           = nfs_file_open,
>         .flush          = nfs_file_flush,
>         .release        = nfs_file_release,
>         .fsync          = nfs_fsync,
>         .lock           = nfs_lock,
>         .flock          = nfs_flock,
>         .sendfile       = nfs_file_sendfile,
>         .check_flags    = nfs_check_flags,
> };
> 
> <3> nfs address space operations:
>     All functions from nfs_file_aops:
> 
>       struct address_space_operations nfs_file_aops = {
>         .readpage = nfs_readpage,
>         .readpages = nfs_readpages,
>         .set_page_dirty = __set_page_dirty_nobuffers,
>         .writepage = nfs_writepage,
>         .writepages = nfs_writepages,
>         .prepare_write = nfs_prepare_write,
>         .commit_write = nfs_commit_write,
>         .invalidatepage = nfs_invalidate_page,
>         .releasepage = nfs_release_page,
> #ifdef CONFIG_NFS_DIRECTIO
>         .direct_IO = nfs_direct_IO,
> #endif
>      };
> 
> <4> NFS RPC procedures:
> 
>    All functions from nfs_v[2,3,4]_clientops:
>     I only list the nfs_v3 rpc procedures:
>      struct nfs_rpc_ops      nfs_v3_clientops = {
>         .version        = 3,                    /* protocol version */
>         .dentry_ops     = &nfs_dentry_operations,
>         .dir_inode_ops  = &nfs3_dir_inode_operations,
>         .file_inode_ops = &nfs3_file_inode_operations,
>         .getroot        = nfs3_proc_get_root,
>         .getattr        = nfs3_proc_getattr,
>         .setattr        = nfs3_proc_setattr,
>         .lookup         = nfs3_proc_lookup,
>         .access         = nfs3_proc_access,
>         .readlink       = nfs3_proc_readlink,
>         .read           = nfs3_proc_read,
>         .write          = nfs3_proc_write,
>         .commit         = nfs3_proc_commit,
>         .create         = nfs3_proc_create,
>         .remove         = nfs3_proc_remove,
>         .unlink_setup   = nfs3_proc_unlink_setup,
>         .unlink_done    = nfs3_proc_unlink_done,
>         .rename         = nfs3_proc_rename,
>         .link           = nfs3_proc_link,
>         .symlink        = nfs3_proc_symlink,
>         .mkdir          = nfs3_proc_mkdir,
>         .rmdir          = nfs3_proc_rmdir,
>         .readdir        = nfs3_proc_readdir,
>         .mknod          = nfs3_proc_mknod,
>         .statfs         = nfs3_proc_statfs,
>         .fsinfo         = nfs3_proc_fsinfo,
>         .pathconf       = nfs3_proc_pathconf,
>         .decode_dirent  = nfs3_decode_dirent,
>         .read_setup     = nfs3_proc_read_setup,
>         .read_done      = nfs3_read_done,
>         .write_setup    = nfs3_proc_write_setup,
>         .write_done     = nfs3_write_done,
>         .commit_setup   = nfs3_proc_commit_setup,
>         .commit_done    = nfs3_commit_done,
>         .file_open      = nfs_open,
>         .file_release   = nfs_release,
>         .lock           = nfs3_proc_lock,
>         .clear_acl_cache = nfs3_forget_cached_acls,
>     };
> 
>   The LKET already has syscall and iosyscall trace hooks. So with the 
> above trace hooks, LKET could trace different layer of NFS operations:
>    --> Syscall
>       --> struct file_operations
>           --> struct address_space_operations
>                --> struct nfs_rpc_ops
> 
> ======================= Server Side =============================
> 
> <1> nfsd_dispatch
>    This is the NFS dispatching function sit on top of RPC.
> 
> <2> NFS RPC procedures:
> 
>     For NFSv4, it will be nfsd4_proc_compound
> 
>     For NFSv2, NFSv3, it will be the functions from nfsd_procedures[2,3]
> 
>     Here is a list for NFSv3, NFSv2 are almost the same:
>       nfsd3_proc_null,
>       nfsd3_proc_getattr,
>       nfsd3_proc_setattr,
>       nfsd3_proc_lookup,
>       nfsd3_proc_access,
>       nfsd3_proc_readlink,
>       nfsd3_proc_read,
>       nfsd3_proc_write,
>       nfsd3_proc_create,
>       nfsd3_proc_mkdir,
>       nfsd3_proc_symlink,
>       nfsd3_proc_mknod,
>       nfsd3_proc_remove,
>       nfsd3_proc_rmdir,
>       nfsd3_proc_rename,
>       nfsd3_proc_link,
>       nfsd3_proc_readdir,
>       nfsd3_proc_readdirplus,readdirplus,
>       nfsd3_proc_fsstat,
>       nfsd3_proc_fsinfo,
>       nfsd3_proc_pathconf,
>       nfsd3_proc_commit,
> 
> <3> NFSD file VFS operations
> 
>      The functions nfsd_xxx from "fs/nfsd/vfs.c"
> 
> With the above server side trace hooks, LKET could trace NFS operations 
> at different layer:
> 
>      nfsd_dispatch -->
>         --> NFS RPC Procedures
>            --> NFS VFS file operations
> 
> 
>   What I didn't list about NFS operations includes authentication, NFSv4 
> callback and RPC(I prefer to use a separate set of trace hooks for RPC). 
> I am not sure if these operations are also required to be traced. If I 
> missed some important functions or I listed some redundant functions, 
> please feel free to let me know. Any comments will be highly appreciated.
> 
>   Thanks.
> 
> The following is from Li Xuepeng posted on nfs@lists.sourceforge.net 
> which involved some implementations details and its trace point lists is 
> a subset of the above.
> 
> - Guanglei
> 
> Xue Peng Li ??:
>> Hi folks,
>>
>> I am working on NFS trace hooks for SystemTap/LKET. These trace
>> hooks could be used for performance analyzing which will trace both
>> NFS client and server side activities.
>>
>> At the first step I need make sure that the trace hooks I defined
>> are appropriate and every trace hook probes the right places inside
>> the Kernel. So I will be appreciated if you could help me review the
>> following trace hooks.
>>
>>
>> Thanks

[-- Attachment #2: nfs.stp --]
[-- Type: text/plain, Size: 29124 bytes --]

%{
#include <linux/kernel.h>
#include <linux/nfs_fs.h>
%}
/*Get struct nfs_inode from struct inode*/
%{ 
  struct nfs_inode * __nfs_i (struct inode *inode)
  {
    struct nfs_inode * nfsi = NFS_I(inode);

    return (nfsi);
  }
%}

/*Get cache_validity flag from struct inode*/
function __nfsi_cache_valid:long(inode:long)
%{
    struct inode * inode = (struct inode *)(THIS->inode);
    struct nfs_inode * nfsi;
  
    nfsi = __nfs_i(inode);
    THIS->__retvalue = nfsi->cache_validity;
%}

/*Get read_cache_jiffies from struct inode*/
function __nfsi_rcache_time :long (inode:long)
%{
    struct inode * inode = (struct inode *)(THIS->inode);
    struct nfs_inode * nfsi = (struct nfs_inode *) __nfs_i(inode);

    THIS->__retvalue = nfsi->read_cache_jiffies;
%}

/*Get attrtimeo from struct inode*/
function __nfsi_attr_time :long (inode:long)
%{
    struct inode * inode = (struct inode *)(THIS->inode);
    struct nfs_inode * nfsi = (struct nfs_inode *) __nfs_i(inode);

    THIS->__retvalue = nfsi->attrtimeo;
%}

/*Get ndirty from struct inode*/
function __nfsi_ndirty:long (inode:long)
%{
      struct inode *inode = (struct inode *)(THIS->inode);
      struct nfs_inode *nfsi = NFS_I(inode);
 
      THIS->__retvalue = nfsi->ndirty;
%}

/*Get rsize from struct inode*/
function __nfs_server_rsize:long (inode:long)
%{
       struct inode * inode = (struct inode *)(THIS->inode);

       THIS->__retvalue = NFS_SERVER(inode)->rsize;
%}

/*Get wsize from struct inode*/
function __nfs_server_wsize:long (inode:long)
%{
       struct inode * inode = (struct inode *)(THIS->inode);

       THIS->__retvalue = NFS_SERVER(inode)->wsize;
%}

/*Get rpages from struct inode*/
function __nfs_rpages:long (inode:long)
%{
       struct inode * inode = (struct inode *)(THIS->inode);

       THIS->__retvalue = NFS_SERVER(inode)->rpages;
%}

/*Get wpages from struct inode*/
function __nfs_wpages:long(inode:long)
%{
      struct inode *inode = (struct inode*)(THIS->inode);
      THIS->__retvalue = NFS_SERVER(inode)->wpages;
%}

/*Get struct inode from struct page*/
function __p2i :long(page:long)
%{
      struct page *page = (struct page *)(THIS->page);
      THIS->__retvalue = (long)page->mapping->host;
%}

/*Get i_flags from struct page*/
function __p2i_flag : long (page:long)
%{
      struct page *page = (struct page *) (THIS->page);
      THIS->__retvalue = page->mapping->host->i_flags;
%}

/*Get i_state from struct page*/
function __p2i_state :long (page:long)
%{
      struct page *page = (struct page *) (THIS->page);
      THIS->__retvalue = page->mapping->host->i_state;
%}

/*Get i_size from struct page*/
function __p2i_size :long (page:long)
%{
      struct page *page = (struct page *) (THIS->page);
      THIS->__retvalue = page->mapping->host->i_size;
%}

/*Get s_flags from struct page*/
function __p2sb_flag:long (page:long)
%{
      struct page *page = (struct page *)(THIS->page);
      THIS->__retvalue = page->mapping->host->i_sb->s_flags;
%}

function __d_loff_t :long (ppos :long)
%{
     loff_t * ppos = (loff_t *) (THIS->ppos);
     
     THIS->__retvalue =(long) *ppos;
%}

probe nfs.fop.entries = nfs.fop.llseek,
                        nfs.fop.read,
                        nfs.fop.write,
                        nfs.fop.aio_read,
                        nfs.fop.aio_write,
                        nfs.fop.mmap,
                        nfs.fop.open,
                        nfs.fop.flush,
                        nfs.fop.release,
                        nfs.fop.fsync,
                        nfs.fop.lock,
                        nfs.fop.sendfile
{
}

probe nfs.fop.entries.return = nfs.fop.llseek.return,
                        nfs.fop.read.return,
                        nfs.fop.write.return,
                        nfs.fop.aio_read.return,
                        nfs.fop.aio_write.return,
                        nfs.fop.mmap.return,
                        nfs.fop.open.return,
                        nfs.fop.flush.return,
                        nfs.fop.release.return,
                        nfs.fop.fsync.return,
                        nfs.fop.lock.return,
                        nfs.fop.sendfile.return
{
}

/*probe nfs.fop.llseek
 *
 *  Fires when do a llseek operation on nfs,it probes
 *  llseek file operation of nfs
 *
 *  Arguments:
 *     dev : device identifier
 *     ino : inode number
 *     offset : the offset of the file will be repositioned
 *     origin : the original position. The possible value could be:
 *         SEEK_SET
 *               The offset is set to offset bytes.
 *         SEEK_CUR
 *               The offset is set to its current location plus offset bytes.
 *         SEEK_END
 *               The offset is set to the size of the file plus offset bytes.
 *
*/
probe nfs.fop.llseek = kernel.function ("nfs_file_llseek") ?,
                       module("nfs").function("nfs_file_llseek") ?
{
        dev = $filp->f_dentry->d_inode->i_sb->s_dev
        ino = $filp->f_dentry->d_inode->i_ino
        maxbyte = $filp->f_dentry->d_inode->i_sb->s_maxbytes
        offset = $offset
        origin = $origin

        name = "nfs.fop.llseek"
        argstr = sprintf("%d, %d", offset, origin)
}

probe nfs.fop.llseek.return = kernel.function ("nfs_file_llseek").return ?,
                              module("nfs").function("nfs_file_llseek").return ?
{
        name = "nfs.fop.llseek.return"
        retstr = sprintf("%d", $return)
}
/*probe nfs.fop.read
 *
 * Fires when do a read operation on nfs,it probes
 * read file operation of nfs
 * 
 * Arguments:
 *        
 *
*/
probe nfs.fop.read = vfs.do_sync_read
{
        name = "nfs.fop.read"
}

probe nfs.fop.read.return = vfs.do_sync_read.return
{
        name = "nfs.fop.read.return"
}

/*probe nfs.fop.write
 *
 * Fires when do a write operation on nfs,it probes
 * write file operation of nfs
 * 
 * Arguments:
 *        
 *
*/

probe nfs.fop.write = vfs.do_sync_write
{
        name = "nfs.fop.write"
}

probe nfs.fop.write.return = vfs.do_sync_write.return
{
        name = "nfs.fop.write.return"
}

/*probe nfs.fop.aio_read
 *
 * It probes aio_read file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number        
 *    count : read bytes
 *    pos   : current position of file   
 *    buf   : the address of buf in user space
 *    parent_name : parent dir name
 *    file_name : file name
 *    cache_valid : cache related bit mask flag
 *    cache_time : when we started read-caching this inode
 *    attrtimeo :  how long the cached information is assumed
 *                 to be valid.
 *   We need to revalidate the cached attrs for this inode if
 *
 *      jiffies - read_cache_jiffies > attrtimeo
*/
probe nfs.fop.aio_read = kernel.function ("nfs_file_read") ?,
                       module("nfs").function("nfs_file_read") ?
{
        dev = $iocb->ki_filp->f_dentry->d_inode->i_sb->s_dev
        ino = $iocb->ki_filp->f_dentry->d_inode->i_ino

        count = $count
        pos = $pos
        buf = $buf

        parent_name = kernel_string($iocb->ki_filp->f_dentry->d_parent->d_name->name)
        file_name = kernel_string($iocb->ki_filp->f_dentry->d_name->name)


        cache_valid = __nfsi_cache_valid($iocb->ki_filp->f_dentry->d_inode)
        cache_time  = __nfsi_rcache_time($iocb->ki_filp->f_dentry->d_inode)
        attr_time   = __nfsi_attr_time($iocb->ki_filp->f_dentry->d_inode)

        flag =  $iocb->ki_filp->f_flags

        name = "nfs.fop.aio_read"
        argstr = sprintf("%p,%d, %d",buf,count, pos)

        size = count
        units = "bytes"
}


probe nfs.fop.aio_read.return = kernel.function ("nfs_file_read").return ?,
                                module("nfs").function("nfs_file_read").return ?
{
        name = "nfs.fop.aio_read.return"
        retstr = sprintf("%d", $return)

        if ($return > 0) {
                size = $return
                units = "bytes"
        }
}

/*probe nfs.fop.aio_write
 *
 * It probes aio_write file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number        
 *    count : read bytes
 *    pos   : offset of the file 
 *    buf   : the address of buf in user space
 *    parent_name : parent dir name
 *    file_name : file name
 *
*/
probe nfs.fop.aio_write = kernel.function("nfs_file_write") ?,
                          module("nfs").function("nfs_file_write") ?
{
        dev = $iocb->ki_filp->f_dentry->d_inode->i_sb->s_dev
        ino = $iocb->ki_filp->f_dentry->d_inode->i_ino

        count = $count
        pos = $pos
        buf = $buf
               
        parent_name = kernel_string($iocb->ki_filp->f_dentry->d_parent->d_name->name)
        file_name = kernel_string($iocb->ki_filp->f_dentry->d_name->name)

        name = "nfs.fop.aio.write"
        argstr = sprintf("%p, %d, %d", buf, count, pos)

        size = count
        units = "bytes"
}

probe nfs.fop.aio_write.return =  kernel.function("nfs_file_write").return ?,
                          module("nfs").function("nfs_file_write").return ?
{
        name = "nfs.fop.aio_write.return"
        retstr = sprintf("%d", $return)

        if ($return > 0) {
                size = $return
                units = "bytes"
        }
}

/*probe nfs.fop.mmap
 *
 * Fires when do an mmap operation on nfs,
 * it probes mmap operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number        
 *    vm_start :  start address within vm_mm 
 *    vm_end   :  the first byte after end address within vm_mm
 *    vm_flag  :  vm flags
 *    buf   : the address of buf in user space
 *    parent_name : parent dir name
 *    file_name : file name
 *    cache_valid : cache related bit mask flag
 *    cache_time : when we started read-caching this inode
 *    attrtimeo :  how long the cached information is assumed
 *                 to be valid.
 *   We need to revalidate the cached attrs for this inode if
 *
 *      jiffies - read_cache_jiffies > attrtimeo
*/
probe nfs.fop.mmap = kernel.function("nfs_file_mmap") ?,
                     module("nfs").function("nfs_file_mmap") ?
{
        dev = $file->f_dentry->d_inode->i_sb->s_dev
        ino = $file->f_dentry->d_inode->i_ino

        vm_start = $vma->vm_start
        vm_end = $vma->vm_end
        vm_flags = $vma->vm_flags

        parent_name = kernel_string($file->f_dentry->d_parent->d_name->name)
        file_name = kernel_string($file->f_dentry->d_name->name)

        cache_valid = __nfsi_cache_valid($file->f_dentry->d_inode)
        cache_time  = __nfsi_rcache_time($file->f_dentry->d_inode)
        attr_time   = __nfsi_attr_time($file->f_dentry->d_inode)

        name = "nfs.fop.mmap"
        argstr = sprintf("0x%x, 0x%x, 0x%x", vm_start, vm_end, vm_flags)
}

probe nfs.fop.mmap.return = kernel.function("nfs_file_mmap").return ?,
                     module("nfs").function("nfs_file_mmap").return ?
{
        name = "nfs.fop.mmap.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.fop.open
 *
 * Fires when do an open operation on nfs,
 * it probes open file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number        
 *    file_name : file name
 *    flag : file flag
 *    i_size : file length in bytes 
*/
probe nfs.fop.open = kernel.function("nfs_file_open") ?,
                     module("nfs").function("nfs_file_open") ?
{
        dev = $filp->f_dentry->d_inode->i_sb->s_dev
        ino = $inode->i_ino

        filename = kernel_string($filp->f_dentry->d_name->name)
        flag = $filp->f_flags   

        i_size = $inode->i_size
   
        name = "nfs.fop.open"
        argstr = sprintf("%d,%d, %s", flag, ino, filename)
}

probe nfs.fop.open.return = kernel.function("nfs_file_open").return ?,
                            module("nfs").function("nfs_file_open").return ?
{
        name = "nfs.fop.open.return"
        retstr = sprintf("%d", $return)        
}

/*probe nfs.fop.flush
 *
 * Fires when do a flush file operation on nfs,
 * it probes flush file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number        
 *    mode : file mode
 *    ndirty : number of dirty page
*/
probe nfs.fop.flush = kernel.function("nfs_file_flush") ?,
                      module("nfs").function("nfs_file_flush") ?
{
        dev = $file->f_dentry->d_inode->i_sb->s_dev
        ino = $file->f_dentry->d_inode->i_ino;

        mode = $file->f_mode
        ndirty = __nfsi_ndirty($file->f_dentry->d_inode)

        name = "nfs.fop.flush"
        argstr = sprintf("%d",ino)
}

probe nfs.fop.flush.return = kernel.function("nfs_file_flush").return ?,
                      module("nfs").function("nfs_file_flush").return ?
{
        name = "nfs.fop.flush.return"
        retstr = sprintf("%d",$return)
}

/*probe nfs.fop.release
 *
 * Fires when do a release page operation on nfs,
 * it probes release file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number        
 *    mode : file mode
*/
probe nfs.fop.release = kernel.function("nfs_file_release") ?,
                      module("nfs").function("nfs_file_release") ?
{
        dev = $filp->f_dentry->d_inode->i_sb->s_dev
        ino = $inode->i_ino

        mode = $filp->f_mode

        name = "nfs.fop.release"
        argstr = sprintf("%d" , ino)
}

probe nfs.fop.release.return = kernel.function("nfs_file_release").return ?,
                               module("nfs").function("nfs_file_release").return ?
{
        name = "nfs.fop.release.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.fop.fsync
 *
 * Fires when do a fsync operation on nfs,
 * it probes fsync file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number       
 *    ndirty : number of dirty pages 
*/
probe nfs.fop.fsync = kernel.function("nfs_fsync") ?,
                      module("nfs").function("nfs_fsync") ?
{
        dev = $file->f_dentry->d_inode->i_sb->s_dev
        ino = $file->f_dentry->d_inode->i_ino

        ndirty = __nfsi_ndirty($file->f_dentry->d_inode)

        name = "nfs.fop.fsync"
	argstr = sprintf("%d",ino)  
}

probe nfs.fop.fsync.return = kernel.function("nfs_fsync").return ?,
                             module("nfs").function("nfs_fsync").return ?
{
        name = "nfs.fop.fsync.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.fop.lock
 *
 * Fires when do a file lock operation on nfs,
 * it probes lock file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number      
 *    i_mode : file type and access rights
 *    cmd : cmd arguments
 *    fl_type :lock type
 *    fl_flag : lock flags
 *    fl_start : starting offset of locked region 
 *    fl_end   : ending offset of locked region  
*/
probe nfs.fop.lock = kernel.function("nfs_lock") ?,
                     module("nfs").function("nfs_lock") ?
{
        dev = $filp->f_dentry->d_inode->i_sb->s_dev
        ino = $filp->f_dentry->d_inode->i_ino
 
        i_mode = $filp->f_dentry->d_inode->i_mode
        cmd = $cmd
 
        fl_type = $fl->fl_type
        fl_flag = $fl->fl_flags
        fl_start = $fl->fl_start
        fl_end  = $fl->fl_end

        name = "nfs.fop.lock"
        argstr = sprintf("%d,%d",cmd,i_mode)
}

probe nfs.fop.lock.return = kernel.function("nfs_lock").return ?,
                             module("nfs").function("nfs_lock").return ?
{
         name = "nfs.fop.lock.return"
         retstr = sprintf("%d",$return)
}


/*probe nfs.fop.sendfile
 *
 * Fires when do a send file  operation on nfs,
 * it probes sendfile file operation of nfs
 * 
 * Arguments:
 *    dev : device identifier
 *    ino : inode number     
 *    count : read bytes
 *    ppos : current position of file
 *    cache_valid : cache related bit mask flag
 *    cache_time : when we started read-caching this inode
 *    attrtimeo :  how long the cached information is assumed
 *                 to be valid.
 *   We need to revalidate the cached attrs for this inode if
 *
 *      jiffies - read_cache_jiffies > attrtimeo
*/
probe nfs.fop.sendfile = kernel.function("nfs_file_sendfile") ?,
                              module("nfs").function("nfs_file_sendfile") ?
{

        dev = $filp->f_dentry->d_inode->i_sb->s_dev
        ino = $filp->f_dentry->d_inode->i_ino

        count = $count
        ppos  = __d_loff_t($ppos)

        cache_valid = __nfsi_cache_valid($filp->f_dentry->d_inode)
        cache_time  = __nfsi_rcache_time($filp->f_dentry->d_inode)
        attr_time   = __nfsi_attr_time($filp->f_dentry->d_inode)


        name = "nfs.fop.sendfile"
        argstr = sprintf("%d,%d", count,ppos)

        size = count
        units = "bytes"
}

probe nfs.fop.sendfile.return = kernel.function("nfs_file_sendfile").return ?,
                              module("nfs").function("nfs_file_sendfile").return ?
{
        name = "nfs.fopsendfile.return"
        retstr = sprintf("%d", $return)

        if ($return > 0) {
                size = $return
                units = "bytes"
        }
}

/*probe nfs.fop.check_flags
 *
 * Fires when do a checking flag  operation on nfs,
 * it probes check_flag file operation of nfs
 * 
 * Arguments:
 *    flag : file flag
*/
probe nfs.fop.check_flags =  kernel.function("nfs_check_flags") ?,
                             module("nfs").function("nfs_check_flags") ?
{
        flag = $flags
        
        name = "nfs.fop.check_flags"
        argstr = sprintf("%d",flag)
}

probe nfs.fop.check_flags.return =  kernel.function("nfs_check_flags").return ?,
                             module("nfs").function("nfs_check_flags").return ?
{
        name = "nfs.fop.check_flags.return"
        retstr = sprintf("%d",$return)
}

probe nfs.aop.entries = nfs.aop.readpage,
                        nfs.aop.readpages,
                        nfs.aop.writepage,
                        nfs.aop.writepages,
                        nfs.aop.prepare_write,
                        nfs.aop.commit_write,
                        nfs.aop.release_page
{
}
 
probe nfs.aop.entries.return = nfs.aop.readpage.return,
                        nfs.aop.readpages.return,
                        nfs.aop.writepage.return,
                        nfs.aop.writepages.return,
                        nfs.aop.prepare_write.return,
                        nfs.aop.commit_write.return,
                        nfs.aop.release_page.return
{
}

/* probe nfs.aop.readpage
 *
 *   Read the page ,only fies when a previous async
 *   read operation failed
 *
 * Arguments:
 *   __page : the address of page
 *   dev : device identifier
 *   ino : inode number    
 *   i_flag : file flags
 *   i_size : file length in bytes
 *   sb_flag : super block flags
 *   file  : file argument
 *   page_index : offset within mapping, can used a 
                  page identifier and position identifier
                  in the page frame
 *   rsize :  read size  (in bytes)
 *   size :  number of pages to be read in this execution 
 */
probe nfs.aop.readpage = kernel.function ("nfs_readpage") ?,
        module("nfs").function ("nfs_readpage") ?
{
        __page = $page
        dev = __page_dev(__page)
        ino = __page_ino(__page)

        i_flag = __p2i_flag($page) 
        i_size = __p2i_size($page)
 
        sb_flag = __p2sb_flag($page) 

        file = $file
        page_index = $page->index
        
        __inode = __p2i($page) 
        rsize = __nfs_server_rsize(__inode)

        name = "nfs.aop.readpage"
        argstr = sprintf("%d,%d" , page_index,r_size)

        size = 1
        units = "pages"
}

probe nfs.aop.readpage.return = kernel.function ("nfs_readpage").return ?,
        module("nfs").function ("nfs_readpage").return ?
{
        name = "nfs.aop.readpage.return"
        retstr = sprintf("%d", $return)

        size = 1
        units = "pages"
}

/* probe nfs.aop.readpages
 *
 * Fies when in readahead way,read several pages once
 * Arguments:
 *   dev : device identifier
 *   ino : inode number   
 *   nr_pages :  number of pages to be read in this execution 
 *   file : filp argument
 *   rpages : read size (in pages) 
 *   rsize  : read size (in bytes)
 *   size :  number of pages to be read in this execution 
 */
probe nfs.aop.readpages =  kernel.function ("nfs_readpages") ?,
        module("nfs").function ("nfs_readpages") ?
{
        dev = $mapping->host->i_sb->s_dev
        ino = $mapping->host->i_ino

        nr_pages = $nr_pages
        file = $filp

        rpages = __nfs_rpages($mapping->host)
        rsize  = __nfs_server_rsize($mapping->host)

        name = "nfs.aop.readpages"
        argstr = sprintf("%d" , nr_pages)

        size = nr_pages
        units = "pages"
}

probe nfs.aop.readpages.return = kernel.function ("nfs_readpages").return ?,
        module("nfs").function ("nfs_readpages").return ?
{
        name = "nfs.aop.readpages.return"
        retstr = sprintf("%d", $return)


        if($return > 0 )
        {
            size = retstr
        }
        units = "pages"
}
/*probe nfs.aop.set_page_dirty
 *
 *   __set_page_dirty_nobuffers is used to set a page dirty,but
 *   not all the buffers.
 *
 *  Arguments:
 *     __page : the address of page
 *      page_flag : page flags
*/
probe nfs.aop.set_page_dirty =
            kernel.function ("__set_page_dirty_nobuffers") ?,
             module("nfs").function ("__set_page_dirty_nobuffers") ?
{
 /*       dev = $mapping->host->i_sb->s_dev
        devname = __find_bdevname(dev, $mapping->host->i_sb->s_bdev)
        ino = $mapping->host->i_ino
*/
        __page = $page
        page_flag = $page->flags

        name = "nfs.aop.set_page_dirty"
        argstr = sprintf("%d",flag)
}

probe nfs.aop.set_page_dirty.return =
            kernel.function ("__set_page_dirty_nobuffers") .return?,
            module("nfs").function ("__set_page_dirty_nobuffers").return ?
{
        name = "nfs.aop.set_page_dirty.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.aop.writepage
 *
 *   Write an mapped page to the server
 *
 *  Arguments:
 *     __page : the address of page
 *     dev : device identifier
 *     ino : inode number  
 *     for_reclaim : a flag of writeback_control, indicates if it's invoked from the page allocator 
 *     for_kupdate : a flag of writeback_control, indicates if it's a kupdate writeback
 *      The priority of wb is decided by above two flags
 *     i_flag : file flags
 *     i_size : file length in bytes
 *     i_state : inode state flags
 *     sb_flag : super block flags
 *     page_index : offset within mapping, can used a 
                    page identifier and position identifier
                    in the page frame
 *     wsize :  write size
 *     size  :  number of pages to be written in this execution 
*/
probe nfs.aop.writepage =  kernel.function ("nfs_writepage") ?,
             module("nfs").function ("nfs_writepage") ?
{
        __page = $page
        dev = __page_dev(__page)
        ino = __page_ino(__page)
        

        for_reclaim = $wbc->for_reclaim
        for_kupdate = $wbc->for_kupdate

        i_flag = __p2i_flag($page) 
        i_state = __p2i_state($page)
        i_size = __p2i_size($page)

        sb_flag = __p2sb_flag($page) 


        page_index = $page->index

        __inode = __p2i($page)
        wsize = __nfs_server_wsize(__inode)            
 
        name = "nfs.aop.writepage"
        argstr = sprintf("%d",page_index)

        size = 1
        units = "pages"
}

probe nfs.aop.writepage.return =  kernel.function ("nfs_writepage").return ?,
             module("nfs").function ("nfs_writepage").return ?
{
        name = "nfs.aop.writepage.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.aop.writepages
 *  Write several dirty pages to the serve
 *Arguments:
 *     dev : device identifier
 *     ino : inode number  
 *     for_reclaim : a flag of writeback_control, indicates if it's invoked from the page allocator 
 *     for_kupdate : a flag of writeback_control, indicates if it's a kupdate writeback
 *      The priority of wb is decided by above two flags
 *      wsize :  write size
 *      wpages : write size (in pages)
 *      nr_to_write : number of pages to be written in this execution  
 *      size : number of pages to be written in this execution  
*/
probe nfs.aop.writepages =  kernel.function ("nfs_writepages") ?,
             module("nfs").function ("nfs_writepages") ?
{
        dev = $mapping->host->i_sb->s_dev
        ino = $mapping->host->i_ino

        for_reclaim = $wbc->for_reclaim
        for_kupdate = $wbc->for_kupdate
        nr_to_write = $wbc->nr_to_write

        wsize = __nfs_server_wsize($mapping->host)
        wpages = __nfs_wpages($mapping->host)

        name = "nfs.aop.writepages"
        argstr = sprintf("%d",nr_to_write)

        size = nr_to_write
        units = "pages"         
}

probe nfs.aop.writepages.return =  kernel.function ("nfs_writepages").return ?,
             module("nfs").function ("nfs_writepages").return ?
{
        name = "nfs.aop.writepages.return"
        retstr = sprintf("%d", $return)
}
/*probe nfs.aop.prepare_write
 *  Fires when do write operation on nfs.
 *     Prepare a page for writing
 *     Look for a request corresponding to the page. If there
 *     is one, and it belongs to another file, we flush it out
 *     before we try to copy anything into the page. 
 *     Also do the same if we find a request from an existing
 *     dropped page
 *
 *  Arguments:
 *     __page : the address of page
 *     dev : device identifier
 *     ino : inode number 
 *     offset : start address of this write operation 
 *     to     : end address of this write operation 
 *     page_index : offset within mapping, can used a 
                     page identifier and position identifier
                     in the page frame
 *     size   : read bytes
*/
probe nfs.aop.prepare_write=  kernel.function ("nfs_prepare_write") ?,
             module("nfs").function ("nfs_prepare_write") ?
{
        dev = __page_dev(__page)
        devname = __find_bdevname(dev, __page_bdev(__page))
        ino = __page_ino(__page)      
  
        offset = $offset
        to = $to
       
        page_index = $page->index
        __page = $page

        name = "nfs.aop.prepare_write"
        argstr = sprintf("%d", page_index)

        size = to - offset
        units = "bytes"        
}

probe nfs.aop.prepare_write.return = 
                 kernel.function ("nfs_prepare_write").return ?,
                 module("nfs").function ("nfs_prepare_write").return ?
{
        name = "nfs.aop.nfs_prepare_write.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.aop.commit_write
 *  Fires when do a write operation on nfs,
 *  often after prepare_write
 *
 *  Update and possibly write a cached page of an NFS file
 *
 *  Arguments:
 *     __page : the address of page
 *     dev : device identifier
 *     ino : inode number
 *     offset : start address of this write operation 
 *     to     : end address of this write operation
 *     i_flag : file flags
 *     i_size : file length in bytes
 *     sb_flag : super block flags
 *     page_index : offset within mapping, can used a 
                    page identifier and position identifier
                    in the page frame
 *     size   : read bytes
 */ 
probe nfs.aop.commit_write=  kernel.function ("nfs_commit_write") ?,
             module("nfs").function ("nfs_commit_write") ?
{
         __page = $page
        dev = __page_dev(__page)
        ino = __page_ino(__page)

        offset = $offset
        to = $to
      

        i_flag = __p2i_flag($page) 
        i_size = __p2i_size($page)

        sb_flag = __p2sb_flag($page) 

        page_index = $page->index
     
        name = "nfs.aop.commit_write"
        argstr = sprintf("%d, %d",offset , to)

        size = to - offset
        units = "bytes"
}


probe nfs.aop.commit_write.return=  
             kernel.function ("nfs_commit_write").return ?,
             module("nfs").function ("nfs_commit_write").return? 
{
        name = "nfs.aop.nfs_commit_write.return"
        retstr = sprintf("%d", $return)
}

/*probe nfs.aop.release_page
 *  Fires when do a release operation on nfs,
 *  
 *
 *  Arguments:
 *     __page : the address of page
 *     dev : device identifier
 *     ino : inode number
 *     page_index : offset within mapping, can used a 
                    page identifier and position identifier
                    in the page frame
 *     size : release pages
*/
probe nfs.aop.release_page =  kernel.function ("nfs_release_page") ?,
             module("nfs").function ("nfs_release_page")?
{
        __page = $page
        dev = __page_dev(__page)
        ino = __page_ino(__page)

//        gfp = $gfp
        page_index = $page->index

        name = "nfs.aop.releasepage"
        argstr = sprintf("%d", page_index)

        size = 1
        units = "pages"

}  

probe nfs.aop.release_page.return =  kernel.function ("nfs_release_page").return ?,
             module("nfs").function ("nfs_release_page").return?
{
        name = "nfs.aop.nfs_release_page.return"
        retstr = sprintf("%d", $return)
}


  parent reply	other threads:[~2006-08-11  1:57 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-26  9:13 [ltc-perf] draft of nfs event hook Xue Peng Li
2006-07-26  9:13 ` Christoph Hellwig
2006-07-26 13:50 ` Chuck Lever
2006-07-28  3:35   ` Xue Peng Li
2006-07-27 13:57 ` Li Guanglei
2006-07-27 15:29   ` [NFS] " Chuck Lever
2006-07-27 17:01     ` Jose R. Santos
2006-07-27 22:47     ` Li Guanglei
     [not found]       ` <001301c6b1e8$bd7cf590$160b0a0a@ict25eacacc325>
2006-07-28  2:03         ` Li Guanglei
2006-08-11  1:57   ` Xue Peng Li [this message]
2006-08-16  8:56     ` Xue Peng Li
2006-08-22 10:08       ` Xue Peng Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44DBE409.4080907@cn.ibm.com \
    --to=xuepengl@cn.ibm.com \
    --cc=nfs@lists.sourceforge.net \
    --cc=systemtap@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox