nfsd: add new io class tracepoint

Add some new tracepoints in the nfsd read/write codepaths. The idea
is that this will give us the ability to measure how long each phase of
a read or write operation takes.

Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Jeff Layton 2015-11-17 06:52:23 -05:00 committed by J. Bruce Fields
parent 6b9b21073d
commit 6e8b50d16a
3 changed files with 79 additions and 0 deletions

View File

@ -7,6 +7,7 @@
#ifndef _LINUX_NFSD_NFSFH_H #ifndef _LINUX_NFSD_NFSFH_H
#define _LINUX_NFSD_NFSFH_H #define _LINUX_NFSD_NFSFH_H
#include <linux/crc32.h>
#include <linux/sunrpc/svc.h> #include <linux/sunrpc/svc.h>
#include <uapi/linux/nfsd/nfsfh.h> #include <uapi/linux/nfsd/nfsfh.h>
@ -205,6 +206,28 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
return true; return true;
} }
#ifdef CONFIG_CRC32
/**
* knfsd_fh_hash - calculate the crc32 hash for the filehandle
* @fh - pointer to filehandle
*
* returns a crc32 hash for the filehandle that is compatible with
* the one displayed by "wireshark".
*/
static inline u32
knfsd_fh_hash(struct knfsd_fh *fh)
{
return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size);
}
#else
static inline u32
knfsd_fh_hash(struct knfsd_fh *fh)
{
return 0;
}
#endif
#ifdef CONFIG_NFSD_V3 #ifdef CONFIG_NFSD_V3
/* /*
* The wcc data stored in current_fh should be cleared * The wcc data stored in current_fh should be cleared

View File

@ -8,6 +8,47 @@
#define _NFSD_TRACE_H #define _NFSD_TRACE_H
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include "nfsfh.h"
DECLARE_EVENT_CLASS(nfsd_io_class,
TP_PROTO(struct svc_rqst *rqstp,
struct svc_fh *fhp,
loff_t offset,
int len),
TP_ARGS(rqstp, fhp, offset, len),
TP_STRUCT__entry(
__field(__be32, xid)
__field_struct(struct knfsd_fh, fh)
__field(loff_t, offset)
__field(int, len)
),
TP_fast_assign(
__entry->xid = rqstp->rq_xid,
fh_copy_shallow(&__entry->fh, &fhp->fh_handle);
__entry->offset = offset;
__entry->len = len;
),
TP_printk("xid=0x%x fh=0x%x offset=%lld len=%d",
__be32_to_cpu(__entry->xid), knfsd_fh_hash(&__entry->fh),
__entry->offset, __entry->len)
)
#define DEFINE_NFSD_IO_EVENT(name) \
DEFINE_EVENT(nfsd_io_class, name, \
TP_PROTO(struct svc_rqst *rqstp, \
struct svc_fh *fhp, \
loff_t offset, \
int len), \
TP_ARGS(rqstp, fhp, offset, len))
DEFINE_NFSD_IO_EVENT(read_start);
DEFINE_NFSD_IO_EVENT(read_opened);
DEFINE_NFSD_IO_EVENT(read_io_done);
DEFINE_NFSD_IO_EVENT(read_done);
DEFINE_NFSD_IO_EVENT(write_start);
DEFINE_NFSD_IO_EVENT(write_opened);
DEFINE_NFSD_IO_EVENT(write_io_done);
DEFINE_NFSD_IO_EVENT(write_done);
#include "state.h" #include "state.h"

View File

@ -42,6 +42,7 @@
#include "nfsd.h" #include "nfsd.h"
#include "vfs.h" #include "vfs.h"
#include "trace.h"
#define NFSDDBG_FACILITY NFSDDBG_FILEOP #define NFSDDBG_FACILITY NFSDDBG_FILEOP
@ -983,16 +984,23 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct raparms *ra; struct raparms *ra;
__be32 err; __be32 err;
trace_read_start(rqstp, fhp, offset, vlen);
err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
if (err) if (err)
return err; return err;
ra = nfsd_init_raparms(file); ra = nfsd_init_raparms(file);
trace_read_opened(rqstp, fhp, offset, vlen);
err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count); err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count);
trace_read_io_done(rqstp, fhp, offset, vlen);
if (ra) if (ra)
nfsd_put_raparams(file, ra); nfsd_put_raparams(file, ra);
fput(file); fput(file);
trace_read_done(rqstp, fhp, offset, vlen);
return err; return err;
} }
@ -1008,24 +1016,31 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
{ {
__be32 err = 0; __be32 err = 0;
trace_write_start(rqstp, fhp, offset, vlen);
if (file) { if (file) {
err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE); NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE);
if (err) if (err)
goto out; goto out;
trace_write_opened(rqstp, fhp, offset, vlen);
err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
stablep); stablep);
trace_write_io_done(rqstp, fhp, offset, vlen);
} else { } else {
err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
if (err) if (err)
goto out; goto out;
trace_write_opened(rqstp, fhp, offset, vlen);
if (cnt) if (cnt)
err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen,
cnt, stablep); cnt, stablep);
trace_write_io_done(rqstp, fhp, offset, vlen);
fput(file); fput(file);
} }
out: out:
trace_write_done(rqstp, fhp, offset, vlen);
return err; return err;
} }