NFSD: Add a tracepoint to record directory entry encoding
authorChuck Lever <chuck.lever@oracle.com>
Fri, 5 Mar 2021 18:57:40 +0000 (13:57 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 22 Mar 2021 14:19:02 +0000 (10:19 -0400)
Enable watching the progress of directory encoding to capture the
timing of any issues with reading or encoding a directory. The
new tracepoint captures dirent encoding for all NFS versions.

For example, here's what a few NFSv4 directory entries might look
like:

nfsd-989   [002]   468.596265: nfsd_dirent:          fh_hash=0x5d162594 ino=2 name=.
nfsd-989   [002]   468.596267: nfsd_dirent:          fh_hash=0x5d162594 ino=1 name=..
nfsd-989   [002]   468.596299: nfsd_dirent:          fh_hash=0x5d162594 ino=3827 name=zlib.c
nfsd-989   [002]   468.596325: nfsd_dirent:          fh_hash=0x5d162594 ino=3811 name=xdiff
nfsd-989   [002]   468.596351: nfsd_dirent:          fh_hash=0x5d162594 ino=3810 name=xdiff-interface.h
nfsd-989   [002]   468.596377: nfsd_dirent:          fh_hash=0x5d162594 ino=3809 name=xdiff-interface.c

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/trace.h
fs/nfsd/vfs.c

index 92a0973..27a93eb 100644 (file)
@@ -391,6 +391,30 @@ DEFINE_EVENT(nfsd_err_class, nfsd_##name,  \
 DEFINE_NFSD_ERR_EVENT(read_err);
 DEFINE_NFSD_ERR_EVENT(write_err);
 
+TRACE_EVENT(nfsd_dirent,
+       TP_PROTO(struct svc_fh *fhp,
+                u64 ino,
+                const char *name,
+                int namlen),
+       TP_ARGS(fhp, ino, name, namlen),
+       TP_STRUCT__entry(
+               __field(u32, fh_hash)
+               __field(u64, ino)
+               __field(int, len)
+               __dynamic_array(unsigned char, name, namlen)
+       ),
+       TP_fast_assign(
+               __entry->fh_hash = fhp ? knfsd_fh_hash(&fhp->fh_handle) : 0;
+               __entry->ino = ino;
+               __entry->len = namlen;
+               memcpy(__get_str(name), name, namlen);
+               __assign_str(name, name);
+       ),
+       TP_printk("fh_hash=0x%08x ino=%llu name=%.*s",
+               __entry->fh_hash, __entry->ino,
+               __entry->len, __get_str(name))
+)
+
 #include "state.h"
 #include "filecache.h"
 #include "vfs.h"
index fd6be35..15adf1f 100644 (file)
@@ -1968,8 +1968,9 @@ static int nfsd_buffered_filldir(struct dir_context *ctx, const char *name,
        return 0;
 }
 
-static __be32 nfsd_buffered_readdir(struct file *file, nfsd_filldir_t func,
-                                   struct readdir_cd *cdp, loff_t *offsetp)
+static __be32 nfsd_buffered_readdir(struct file *file, struct svc_fh *fhp,
+                                   nfsd_filldir_t func, struct readdir_cd *cdp,
+                                   loff_t *offsetp)
 {
        struct buffered_dirent *de;
        int host_err;
@@ -2015,6 +2016,8 @@ static __be32 nfsd_buffered_readdir(struct file *file, nfsd_filldir_t func,
                        if (cdp->err != nfs_ok)
                                break;
 
+                       trace_nfsd_dirent(fhp, de->ino, de->name, de->namlen);
+
                        reclen = ALIGN(sizeof(*de) + de->namlen,
                                       sizeof(u64));
                        size -= reclen;
@@ -2062,7 +2065,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
                goto out_close;
        }
 
-       err = nfsd_buffered_readdir(file, func, cdp, offsetp);
+       err = nfsd_buffered_readdir(file, fhp, func, cdp, offsetp);
 
        if (err == nfserr_eof || err == nfserr_toosmall)
                err = nfs_ok; /* can still be found in ->err */