diff mbox series

[RFC,08/21] NFSD: Add tracepoint for nfsd_access()

Message ID 160029257508.29208.10177582417317460106.stgit@klimt.1015granger.net
State New
Headers show
Series NFSD operation monitoring tracepoints | expand

Commit Message

Chuck Lever Sept. 16, 2020, 9:42 p.m. UTC
It is possible to use this tracepoint for several purposes,
including troubleshooting export permission problems and auditing
accesses to files.

nfsd-1025  [002]   256.807403: nfsd_permission:      xid=0x12147d7a type=REG access=WRITE|SATTR|OWNER_OVERRIDE owner=1046/100 user=1046/100 name=.clang-format status=0

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/trace.c |    2 ++
 fs/nfsd/trace.h |   44 ++++++++++++++++++++++++++++++++++++++++++++
 fs/nfsd/vfs.c   |    1 +
 3 files changed, 47 insertions(+)
diff mbox series

Patch

diff --git a/fs/nfsd/trace.c b/fs/nfsd/trace.c
index f008b95ceec2..e6857b8bdf2b 100644
--- a/fs/nfsd/trace.c
+++ b/fs/nfsd/trace.c
@@ -1,4 +1,6 @@ 
 // SPDX-License-Identifier: GPL-2.0
 
+#include <linux/nfs4.h>
+
 #define CREATE_TRACE_POINTS
 #include "trace.h"
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index 77b7e8a45776..4167726fe835 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -511,6 +511,50 @@  TRACE_EVENT(nfsd_clid_inuse_err,
 		__entry->cl_boot, __entry->cl_id)
 )
 
+TRACE_EVENT(nfsd_access,
+	TP_PROTO(
+		const struct svc_rqst *rqstp,
+		const struct dentry *dentry,
+		int access,
+		__be32 status
+	),
+	TP_ARGS(rqstp, dentry, access, status),
+	TP_STRUCT__entry(
+		__field(u32, xid)
+		__field(unsigned long, type)
+		__field(unsigned long, access)
+		__field(uid_t, owner)
+		__field(gid_t, owner_group)
+		__field(uid_t, user)
+		__field(gid_t, user_group)
+		__field(int, status)
+		__dynamic_array(unsigned char, name, dentry->d_name.len + 1)
+	),
+	TP_fast_assign(
+		const struct inode *inode = d_inode(dentry);
+
+		__entry->xid = be32_to_cpu(rqstp->rq_xid);
+		__entry->type = inode->i_mode & S_IFMT;
+		__entry->access = access;
+		__entry->owner = __kuid_val(inode->i_uid);
+		__entry->owner_group = __kgid_val(inode->i_gid);
+		__entry->user = __kuid_val(current_fsuid());
+		__entry->user_group = __kgid_val(current_fsgid());
+		__entry->status = be32_to_cpu(status);
+		memcpy(__get_str(name), dentry->d_name.name,
+		       dentry->d_name.len);
+		__get_str(name)[dentry->d_name.len] = '\0';
+	),
+	TP_printk("xid=0x%08x type=%s access=%s owner=%u/%u user=%u/%u name=%s status=%d",
+		__entry->xid,
+		show_inode_type(__entry->type),
+		show_perm_flags(__entry->access),
+		__entry->owner, __entry->owner_group,
+		__entry->user, __entry->user_group,
+		__get_str(name), __entry->status
+	)
+);
+
 /*
  * from fs/nfsd/filecache.h
  */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a311593ac976..0d354531ed19 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -687,6 +687,7 @@  nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
 			sresult |= map->access;
 
 			err2 = nfsd_permission(rqstp, export, dentry, map->how);
+			trace_nfsd_access(rqstp, dentry, map->how, err2);
 			switch (err2) {
 			case nfs_ok:
 				result |= map->access;