Commit 6019ce07 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Add a tracepoint to record directory entry encoding



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: default avatarChuck Lever <chuck.lever@oracle.com>
parent 1416f435
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -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"
+6 −3
Original line number Diff line number Diff line
@@ -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 */