nfsd: Add a tracepoint for errors in nfsd4_clone_file_range()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 19 Dec 2021 01:38:00 +0000 (20:38 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Sat, 8 Jan 2022 19:42:02 +0000 (14:42 -0500)
Since a clone error commit can cause the boot verifier to change,
we should trace those errors.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
[ cel: Addressed a checkpatch.pl splat in fs/nfsd/vfs.h ]

fs/nfsd/nfs4proc.c
fs/nfsd/trace.h
fs/nfsd/vfs.c
fs/nfsd/vfs.h

index 56405fc..4305708 100644 (file)
@@ -1101,7 +1101,7 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (status)
                goto out;
 
-       status = nfsd4_clone_file_range(src, clone->cl_src_pos,
+       status = nfsd4_clone_file_range(rqstp, src, clone->cl_src_pos,
                        dst, clone->cl_dst_pos, clone->cl_count,
                        EX_ISSYNC(cstate->current_fh.fh_export));
 
index 6afb320..a0b2b8d 100644 (file)
@@ -399,6 +399,56 @@ TRACE_EVENT(nfsd_dirent,
        )
 )
 
+DECLARE_EVENT_CLASS(nfsd_copy_err_class,
+       TP_PROTO(struct svc_rqst *rqstp,
+                struct svc_fh  *src_fhp,
+                loff_t         src_offset,
+                struct svc_fh  *dst_fhp,
+                loff_t         dst_offset,
+                u64            count,
+                int            status),
+       TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, count, status),
+       TP_STRUCT__entry(
+               __field(u32, xid)
+               __field(u32, src_fh_hash)
+               __field(loff_t, src_offset)
+               __field(u32, dst_fh_hash)
+               __field(loff_t, dst_offset)
+               __field(u64, count)
+               __field(int, status)
+       ),
+       TP_fast_assign(
+               __entry->xid = be32_to_cpu(rqstp->rq_xid);
+               __entry->src_fh_hash = knfsd_fh_hash(&src_fhp->fh_handle);
+               __entry->src_offset = src_offset;
+               __entry->dst_fh_hash = knfsd_fh_hash(&dst_fhp->fh_handle);
+               __entry->dst_offset = dst_offset;
+               __entry->count = count;
+               __entry->status = status;
+       ),
+       TP_printk("xid=0x%08x src_fh_hash=0x%08x src_offset=%lld "
+                       "dst_fh_hash=0x%08x dst_offset=%lld "
+                       "count=%llu status=%d",
+                 __entry->xid, __entry->src_fh_hash, __entry->src_offset,
+                 __entry->dst_fh_hash, __entry->dst_offset,
+                 (unsigned long long)__entry->count,
+                 __entry->status)
+)
+
+#define DEFINE_NFSD_COPY_ERR_EVENT(name)               \
+DEFINE_EVENT(nfsd_copy_err_class, nfsd_##name,         \
+       TP_PROTO(struct svc_rqst        *rqstp,         \
+                struct svc_fh          *src_fhp,       \
+                loff_t                 src_offset,     \
+                struct svc_fh          *dst_fhp,       \
+                loff_t                 dst_offset,     \
+                u64                    count,          \
+                int                    status),        \
+       TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, \
+               count, status))
+
+DEFINE_NFSD_COPY_ERR_EVENT(clone_file_range_err);
+
 #include "state.h"
 #include "filecache.h"
 #include "vfs.h"
index c22511d..70ea7e0 100644 (file)
@@ -40,6 +40,7 @@
 #include "../internal.h"
 #include "acl.h"
 #include "idmap.h"
+#include "xdr4.h"
 #endif /* CONFIG_NFSD_V4 */
 
 #include "nfsd.h"
@@ -517,8 +518,15 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
 }
 #endif
 
-__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
-               struct nfsd_file *nf_dst, u64 dst_pos, u64 count, bool sync)
+static struct nfsd4_compound_state *nfsd4_get_cstate(struct svc_rqst *rqstp)
+{
+       return &((struct nfsd4_compoundres *)rqstp->rq_resp)->cstate;
+}
+
+__be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
+               struct nfsd_file *nf_src, u64 src_pos,
+               struct nfsd_file *nf_dst, u64 dst_pos,
+               u64 count, bool sync)
 {
        struct file *src = nf_src->nf_file;
        struct file *dst = nf_dst->nf_file;
@@ -545,6 +553,12 @@ __be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
                if (!status)
                        status = commit_inode_metadata(file_inode(src));
                if (status < 0) {
+                       trace_nfsd_clone_file_range_err(rqstp,
+                                       &nfsd4_get_cstate(rqstp)->save_fh,
+                                       src_pos,
+                                       &nfsd4_get_cstate(rqstp)->current_fh,
+                                       dst_pos,
+                                       count, status);
                        nfsd_reset_boot_verifier(net_generic(nf_dst->nf_net,
                                                 nfsd_net_id));
                        ret = nfserrno(status);
index b21b76e..9f56dcb 100644 (file)
@@ -57,7 +57,8 @@ __be32          nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
                    struct xdr_netobj *);
 __be32         nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
                                    struct file *, loff_t, loff_t, int);
-__be32         nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
+__be32         nfsd4_clone_file_range(struct svc_rqst *rqstp,
+                                      struct nfsd_file *nf_src, u64 src_pos,
                                       struct nfsd_file *nf_dst, u64 dst_pos,
                                       u64 count, bool sync);
 #endif /* CONFIG_NFSD_V4 */