Re: [PATCH 3/7] NFSv4.2 add tracepoint to COPY

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> On Oct 18, 2021, at 6:03 PM, Olga Kornievskaia <olga.kornievskaia@xxxxxxxxx> wrote:
> 
> From: Olga Kornievskaia <kolga@xxxxxxxxxx>
> 
> Add a tracepoint to the COPY operation.
> 
> Signed-off-by: Olga Kornievskaia <kolga@xxxxxxxxxx>
> ---
> fs/nfs/nfs42proc.c |   1 +
> fs/nfs/nfs4trace.h | 101 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 102 insertions(+)
> 
> diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
> index c36824888601..a072cdaf7bdc 100644
> --- a/fs/nfs/nfs42proc.c
> +++ b/fs/nfs/nfs42proc.c
> @@ -367,6 +367,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
> 
> 	status = nfs4_call_sync(dst_server->client, dst_server, &msg,
> 				&args->seq_args, &res->seq_res, 0);
> +	trace_nfs4_copy(src_inode, dst_inode, args, res, nss, status);

There seems to be a lot of logic in _nfs42_proc_copy() that
happens after this tracepoint. Are you sure this is the
best placement, or do you want to capture failures that
might happen in the subsequent logic?


> 	if (status == -ENOTSUPP)
> 		dst_server->caps &= ~NFS_CAP_COPY;
> 	if (status)
> diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h
> index ba338ee4a82b..4beb59d78ff3 100644
> --- a/fs/nfs/nfs4trace.h
> +++ b/fs/nfs/nfs4trace.h
> @@ -2540,6 +2540,107 @@ DECLARE_EVENT_CLASS(nfs4_sparse_event,
> DEFINE_NFS4_SPARSE_EVENT(nfs4_fallocate);
> DEFINE_NFS4_SPARSE_EVENT(nfs4_deallocate);
> 
> +TRACE_EVENT(nfs4_copy,
> +		TP_PROTO(
> +			const struct inode *src_inode,
> +			const struct inode *dst_inode,
> +			const struct nfs42_copy_args *args,
> +			const struct nfs42_copy_res *res,
> +			const struct nl4_server *nss,
> +			int error
> +		),
> +
> +		TP_ARGS(src_inode, dst_inode, args, res, nss, error),
> +
> +		TP_STRUCT__entry(
> +			__field(unsigned long, error)
> +			__field(u32, src_fhandle)
> +			__field(u32, src_fileid)
> +			__field(u32, dst_fhandle)
> +			__field(u32, dst_fileid)
> +			__field(dev_t, src_dev)
> +			__field(dev_t, dst_dev)
> +			__field(int, src_stateid_seq)
> +			__field(u32, src_stateid_hash)
> +			__field(int, dst_stateid_seq)
> +			__field(u32, dst_stateid_hash)
> +			__field(loff_t, src_offset)
> +			__field(loff_t, dst_offset)
> +			__field(bool, sync)
> +			__field(loff_t, len)
> +			__field(int, res_stateid_seq)
> +			__field(u32, res_stateid_hash)
> +			__field(loff_t, res_count)
> +			__field(bool, res_sync)
> +			__field(bool, res_cons)
> +			__field(bool, intra)
> +		),
> +
> +		TP_fast_assign(
> +			const struct nfs_inode *src_nfsi = NFS_I(src_inode);
> +			const struct nfs_inode *dst_nfsi = NFS_I(dst_inode);
> +
> +			__entry->src_fileid = src_nfsi->fileid;
> +			__entry->src_dev = src_inode->i_sb->s_dev;
> +			__entry->src_fhandle = nfs_fhandle_hash(args->src_fh);
> +			__entry->src_offset = args->src_pos;
> +			__entry->dst_fileid = dst_nfsi->fileid;
> +			__entry->dst_dev = dst_inode->i_sb->s_dev;
> +			__entry->dst_fhandle = nfs_fhandle_hash(args->dst_fh);
> +			__entry->dst_offset = args->dst_pos;
> +			__entry->len = args->count;
> +			__entry->sync = args->sync;
> +			__entry->error = error < 0 ? -error : 0;
> +			__entry->src_stateid_seq =
> +				be32_to_cpu(args->src_stateid.seqid);
> +			__entry->src_stateid_hash =
> +				nfs_stateid_hash(&args->src_stateid);
> +			__entry->dst_stateid_seq =
> +				be32_to_cpu(args->dst_stateid.seqid);
> +			__entry->dst_stateid_hash =
> +				nfs_stateid_hash(&args->dst_stateid);
> +			__entry->res_stateid_seq = error < 0 ? 0 :
> +				be32_to_cpu(res->write_res.stateid.seqid);
> +			__entry->res_stateid_hash = error < 0 ? 0 :
> +				nfs_stateid_hash(&res->write_res.stateid);
> +			__entry->res_count = error < 0 ? 0 :
> +				res->write_res.count;
> +			__entry->res_sync = error < 0 ? 0 :
> +				res->synchronous;
> +			__entry->res_cons = error < 0 ? 0 :
> +				res->consecutive;
> +			__entry->intra = nss ? 0 : 1;
> +		),

I have some general comments about the ternaries here
and in some of the other patches.

At the very least you should instead have a single check:

	if (error) {
		/* record all the error values */
	} else {
		/* record zeroes */
	}

Although, I recommend a different approach entirely,
and that is to to have /two/ trace points: one for
the success case and one for the error case. That
way the error case can be enabled persistently, as
appropriate, and the success case can be used for
general debugging, which ought to be rare once the
code is working well and we have good error reporting
in user space.

In some instances (maybe not here in copy), the
success tracepoint is completely unnecessary for
everyday operation and can be omitted.

What's your thought about that?


> +
> +		TP_printk(
> +			"error=%ld (%s) intra=%d src_fileid=%02x:%02x:%llu "
> +			"src_fhandle=0x%08x dst_fileid=%02x:%02x:%llu "
> +			"dst_fhandle=0x%08x src_stateid=%d:0x%08x "
> +			"dst_stateid=%d:0x%08x src_offset=%llu dst_offset=%llu "
> +			"len=%llu sync=%d cb_stateid=%d:0x%08x res_sync=%d "
> +			"res_cons=%d res_count=%llu",
> +			-__entry->error,
> +			show_nfsv4_errors(__entry->error),
> +			__entry->intra,
> +			MAJOR(__entry->src_dev), MINOR(__entry->src_dev),
> +			(unsigned long long)__entry->src_fileid,
> +			__entry->src_fhandle,
> +			MAJOR(__entry->dst_dev), MINOR(__entry->dst_dev),
> +			(unsigned long long)__entry->dst_fileid,
> +			__entry->dst_fhandle,
> +			__entry->src_stateid_seq, __entry->src_stateid_hash,
> +			__entry->dst_stateid_seq, __entry->dst_stateid_hash,
> +			__entry->src_offset,
> +			__entry->dst_offset,
> +			__entry->len,
> +			__entry->sync,
> +			__entry->res_stateid_seq, __entry->res_stateid_hash,
> +			__entry->res_sync,
> +			__entry->res_cons,
> +			__entry->res_count
> +		)
> +);
> +
> #endif /* CONFIG_NFS_V4_1 */
> 
> #endif /* _TRACE_NFS4_H */
> -- 
> 2.27.0
> 

--
Chuck Lever







[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux