nfsd: add new io class tracepoint
authorJeff Layton <jlayton@poochiereds.net>
Tue, 17 Nov 2015 11:52:23 +0000 (06:52 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Thu, 14 Jan 2016 22:32:51 +0000 (17:32 -0500)
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>
fs/nfsd/nfsfh.h
fs/nfsd/trace.h
fs/nfsd/vfs.c

index 2087bae..0770bcb 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef _LINUX_NFSD_NFSFH_H
 #define _LINUX_NFSD_NFSFH_H
 
+#include <linux/crc32.h>
 #include <linux/sunrpc/svc.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;
 }
 
+#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
 /*
  * The wcc data stored in current_fh should be cleared
index 0befe76..3287041 100644 (file)
@@ -8,6 +8,47 @@
 #define _NFSD_TRACE_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"
 
index 994d66f..3257c59 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "nfsd.h"
 #include "vfs.h"
+#include "trace.h"
 
 #define NFSDDBG_FACILITY               NFSDDBG_FILEOP
 
@@ -983,16 +984,23 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
        struct raparms  *ra;
        __be32 err;
 
+       trace_read_start(rqstp, fhp, offset, vlen);
        err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
        if (err)
                return err;
 
        ra = nfsd_init_raparms(file);
+
+       trace_read_opened(rqstp, fhp, offset, vlen);
        err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count);
+       trace_read_io_done(rqstp, fhp, offset, vlen);
+
        if (ra)
                nfsd_put_raparams(file, ra);
        fput(file);
 
+       trace_read_done(rqstp, fhp, offset, vlen);
+
        return err;
 }
 
@@ -1008,24 +1016,31 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 {
        __be32                  err = 0;
 
+       trace_write_start(rqstp, fhp, offset, vlen);
+
        if (file) {
                err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
                                NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE);
                if (err)
                        goto out;
+               trace_write_opened(rqstp, fhp, offset, vlen);
                err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
                                stablep);
+               trace_write_io_done(rqstp, fhp, offset, vlen);
        } else {
                err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
                if (err)
                        goto out;
 
+               trace_write_opened(rqstp, fhp, offset, vlen);
                if (cnt)
                        err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen,
                                             cnt, stablep);
+               trace_write_io_done(rqstp, fhp, offset, vlen);
                fput(file);
        }
 out:
+       trace_write_done(rqstp, fhp, offset, vlen);
        return err;
 }