Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f06d3fee authored by Chuck Lever's avatar Chuck Lever Committed by Greg Kroah-Hartman
Browse files

NFSD: Add tracepoints to NFSD's duplicate reply cache



[ Upstream commit 0b175b18648ebedfe255b11a7792f1d76848a8f7 ]

Try to capture DRC failures.

Two additional clean-ups:
- Introduce Doxygen-style comments for the main entry points
- Remove a dprintk that fires for an allocation failure. This was
  the only dprintk in the REPCACHE class.

Reported-by: default avatarkbuild test robot <lkp@intel.com>
[ cel: force typecast for display of checksum values ]
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Stable-dep-of: 3bc8edc98bd4 ("nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent fe142d5c
Loading
Loading
Loading
Loading
+35 −22
Original line number Diff line number Diff line
@@ -20,8 +20,7 @@

#include "nfsd.h"
#include "cache.h"

#define NFSDDBG_FACILITY	NFSDDBG_REPCACHE
#include "trace.h"

/*
 * We use this value to determine the number of hash buckets from the max
@@ -324,8 +323,10 @@ nfsd_cache_key_cmp(const struct svc_cacherep *key,
			const struct svc_cacherep *rp, struct nfsd_net *nn)
{
	if (key->c_key.k_xid == rp->c_key.k_xid &&
	    key->c_key.k_csum != rp->c_key.k_csum)
	    key->c_key.k_csum != rp->c_key.k_csum) {
		++nn->payload_misses;
		trace_nfsd_drc_mismatch(nn, key, rp);
	}

	return memcmp(&key->c_key, &rp->c_key, sizeof(key->c_key));
}
@@ -378,15 +379,22 @@ nfsd_cache_insert(struct nfsd_drc_bucket *b, struct svc_cacherep *key,
	return ret;
}

/*
/**
 * nfsd_cache_lookup - Find an entry in the duplicate reply cache
 * @rqstp: Incoming Call to find
 *
 * Try to find an entry matching the current call in the cache. When none
 * is found, we try to grab the oldest expired entry off the LRU list. If
 * a suitable one isn't there, then drop the cache_lock and allocate a
 * new one, then search again in case one got inserted while this thread
 * didn't hold the lock.
 *
 * Return values:
 *   %RC_DOIT: Process the request normally
 *   %RC_REPLY: Reply from cache
 *   %RC_DROPIT: Do not process the request further
 */
int
nfsd_cache_lookup(struct svc_rqst *rqstp)
int nfsd_cache_lookup(struct svc_rqst *rqstp)
{
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
	struct svc_cacherep	*rp, *found;
@@ -400,7 +408,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
	rqstp->rq_cacherep = NULL;
	if (type == RC_NOCACHE) {
		nfsdstats.rcnocache++;
		return rtn;
		goto out;
	}

	csum = nfsd_cache_csum(rqstp);
@@ -410,10 +418,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
	 * preallocate an entry.
	 */
	rp = nfsd_reply_cache_alloc(rqstp, csum, nn);
	if (!rp) {
		dprintk("nfsd: unable to allocate DRC entry!\n");
		return rtn;
	}
	if (!rp)
		goto out;

	spin_lock(&b->cache_lock);
	found = nfsd_cache_insert(b, rp, nn);
@@ -432,8 +438,10 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)

	/* go ahead and prune the cache */
	prune_bucket(b, nn);
 out:

out_unlock:
	spin_unlock(&b->cache_lock);
out:
	return rtn;

found_entry:
@@ -443,13 +451,13 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)

	/* Request being processed */
	if (rp->c_state == RC_INPROG)
		goto out;
		goto out_trace;

	/* From the hall of fame of impractical attacks:
	 * Is this a user who tries to snoop on the cache? */
	rtn = RC_DOIT;
	if (!test_bit(RQ_SECURE, &rqstp->rq_flags) && rp->c_secure)
		goto out;
		goto out_trace;

	/* Compose RPC reply header */
	switch (rp->c_type) {
@@ -461,20 +469,26 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
		break;
	case RC_REPLBUFF:
		if (!nfsd_cache_append(rqstp, &rp->c_replvec))
			goto out;	/* should not happen */
			goto out_unlock; /* should not happen */
		rtn = RC_REPLY;
		break;
	default:
		WARN_ONCE(1, "nfsd: bad repcache type %d\n", rp->c_type);
	}

	goto out;
out_trace:
	trace_nfsd_drc_found(nn, rqstp, rtn);
	goto out_unlock;
}

/*
 * Update a cache entry. This is called from nfsd_dispatch when
 * the procedure has been executed and the complete reply is in
 * rqstp->rq_res.
/**
 * nfsd_cache_update - Update an entry in the duplicate reply cache.
 * @rqstp: svc_rqst with a finished Reply
 * @cachetype: which cache to update
 * @statp: Reply's status code
 *
 * This is called from nfsd_dispatch when the procedure has been
 * executed and the complete reply is in rqstp->rq_res.
 *
 * We're copying around data here rather than swapping buffers because
 * the toplevel loop requires max-sized buffers, which would be a waste
@@ -487,8 +501,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
 * nfsd failed to encode a reply that otherwise would have been cached.
 * In this case, nfsd_cache_update is called with statp == NULL.
 */
void
nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
void nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
{
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
	struct svc_cacherep *rp = rqstp->rq_cacherep;
+59 −0
Original line number Diff line number Diff line
@@ -310,6 +310,65 @@ TRACE_EVENT(nfsd_file_fsnotify_handle_event,
			__entry->nlink, __entry->mode, __entry->mask)
);

#include "cache.h"

TRACE_DEFINE_ENUM(RC_DROPIT);
TRACE_DEFINE_ENUM(RC_REPLY);
TRACE_DEFINE_ENUM(RC_DOIT);

#define show_drc_retval(x)						\
	__print_symbolic(x,						\
		{ RC_DROPIT, "DROPIT" },				\
		{ RC_REPLY, "REPLY" },					\
		{ RC_DOIT, "DOIT" })

TRACE_EVENT(nfsd_drc_found,
	TP_PROTO(
		const struct nfsd_net *nn,
		const struct svc_rqst *rqstp,
		int result
	),
	TP_ARGS(nn, rqstp, result),
	TP_STRUCT__entry(
		__field(unsigned long long, boot_time)
		__field(unsigned long, result)
		__field(u32, xid)
	),
	TP_fast_assign(
		__entry->boot_time = nn->boot_time;
		__entry->result = result;
		__entry->xid = be32_to_cpu(rqstp->rq_xid);
	),
	TP_printk("boot_time=%16llx xid=0x%08x result=%s",
		__entry->boot_time, __entry->xid,
		show_drc_retval(__entry->result))

);

TRACE_EVENT(nfsd_drc_mismatch,
	TP_PROTO(
		const struct nfsd_net *nn,
		const struct svc_cacherep *key,
		const struct svc_cacherep *rp
	),
	TP_ARGS(nn, key, rp),
	TP_STRUCT__entry(
		__field(unsigned long long, boot_time)
		__field(u32, xid)
		__field(u32, cached)
		__field(u32, ingress)
	),
	TP_fast_assign(
		__entry->boot_time = nn->boot_time;
		__entry->xid = be32_to_cpu(key->c_key.k_xid);
		__entry->cached = (__force u32)key->c_key.k_csum;
		__entry->ingress = (__force u32)rp->c_key.k_csum;
	),
	TP_printk("boot_time=%16llx xid=0x%08x cached-csum=0x%08x ingress-csum=0x%08x",
		__entry->boot_time, __entry->xid, __entry->cached,
		__entry->ingress)
);

#endif /* _NFSD_TRACE_H */

#undef TRACE_INCLUDE_PATH