diff mbox series

[v2,13/27] NFSD: Add tracepoint for nfsd_access()

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

Commit Message

Chuck Lever Sept. 21, 2020, 6:11 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=OK

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

Patch

diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index b4c773530aa8..15b97275b3b4 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -10,6 +10,7 @@ 
 
 #include <linux/tracepoint.h>
 #include <trace/events/fs.h>
+#include <trace/events/nfs.h>
 
 #include "export.h"
 #include "nfsfh.h"
@@ -30,6 +31,50 @@ 
 		{ NFSD_MAY_READ_IF_EXEC,	"READ_IF_EXEC" },	\
 		{ NFSD_MAY_64BIT_COOKIE,	"64BIT_COOKIE" })
 
+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=%s",
+		__entry->xid,
+		show_inode_type(__entry->type),
+		show_nfsd_may_flags(__entry->access),
+		__entry->owner, __entry->owner_group,
+		__entry->user, __entry->user_group,
+		__get_str(name), show_nfs_status(__entry->status)
+	)
+);
+
 TRACE_EVENT(nfsd_setattr_args,
 	TP_PROTO(
 		const struct svc_rqst *rqstp,
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;
diff --git a/include/trace/events/fs.h b/include/trace/events/fs.h
index 2b185d81d9a5..49d3dde471ad 100644
--- a/include/trace/events/fs.h
+++ b/include/trace/events/fs.h
@@ -165,3 +165,13 @@ 
 		{ ATTR_OPEN,		"OPEN" }, \
 		{ ATTR_TIMES_SET,	"TIMES_SET" }, \
 		{ ATTR_TOUCH,		"TOUCH" })
+
+#define show_inode_type(x) \
+	__print_symbolic(x, \
+		{ S_IFIFO,		"FIFO" }, \
+		{ S_IFCHR,		"CHR" }, \
+		{ S_IFDIR,		"DIR" }, \
+		{ S_IFBLK,		"BLK" }, \
+		{ S_IFREG,		"REG" }, \
+		{ S_IFLNK,		"LNK" }, \
+		{ S_IFSOCK,		"SOCK" })