On Tue, 2018-06-26 at 20:13 -0400, Chuck Lever wrote: > > On Jun 26, 2018, at 7:56 PM, Dave Wysochanski <dwysocha@xxxxxxxxxx> wrote: > > > > The existing rpc_print_iostats has a few shortcomings. First, the naming > > is not consistent with other functions in the kernel that display stats. > > Second, it is really displaying stats for an rpc_clnt structure as it > > displays both xprt stats and per-op stats. Third, it does not handle > > rpc_clnt clones, which is important for the one in-kernel tree caller > > of this function, the NFS client's nfs_show_stats function. > > > > Fix all of the above by renaming the rpc_print_iostats to > > rpc_clnt_show_stats and looping through any rpc_clnt clones via > > cl_parent. > > > > Once this interface is fixed, this addresses a problem with NFSv4. > > Before this patch, the /proc/self/mountstats always showed incorrect > > counts for NFSv4 state related opcodes such as SEQUENCE and RENEW. > > These counts were always 0 even though many ops would go over the > > wire. The reason for this is there are multiple rpc_clnt structures > > allocated for any given NFSv4 mount, and inside nfs_show_stats() we callled > > into rpc_print_iostats() which only handled one of them, nfs_server->client. > > Fix these counts by calling sunrpc's new rpc_clnt_show_stats() function, > > which handles cloned rpc_clnt structs and prints the stats together. > > > > Note that one side-effect of the above is that multiple mounts from > > the same NFS server will show identical counts in the above ops due > > to the fact the one rpc_clnt (representing the NFSv4 client state) > > is shared across mounts. > > > > Signed-off-by: Dave Wysochanski <dwysocha@xxxxxxxxxx> > > --- > > fs/nfs/super.c | 2 +- > > include/linux/sunrpc/metrics.h | 6 +++--- > > net/sunrpc/stats.c | 17 ++++++++++++----- > > 3 files changed, 16 insertions(+), 9 deletions(-) > > > > diff --git a/fs/nfs/super.c b/fs/nfs/super.c > > index 5e470e233c83..bdf39fa1bfbc 100644 > > --- a/fs/nfs/super.c > > +++ b/fs/nfs/super.c > > @@ -884,7 +884,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) > > #endif > > seq_printf(m, "\n"); > > > > - rpc_print_iostats(m, nfss->client); > > + rpc_clnt_show_stats(m, nfss->client); > > > > return 0; > > } > > diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h > > index 9baed7b355b2..3daa5b42d871 100644 > > --- a/include/linux/sunrpc/metrics.h > > +++ b/include/linux/sunrpc/metrics.h > > @@ -30,7 +30,7 @@ > > #include <linux/ktime.h> > > #include <linux/spinlock.h> > > > > -#define RPC_IOSTATS_VERS "1.0" > > +#define RPC_IOSTATS_VERS "1.1" > > A quick browse does not reveal a format change in /proc/self/mountstats. > Did I miss it? If there's no change, VERS should stay "1.0". > No there is not a format change, so you're right. Thanks! > > > struct rpc_iostats { > > spinlock_t om_lock; > > @@ -82,7 +82,7 @@ void rpc_count_iostats(const struct rpc_task *, > > struct rpc_iostats *); > > void rpc_count_iostats_metrics(const struct rpc_task *, > > struct rpc_iostats *); > > -void rpc_print_iostats(struct seq_file *, struct rpc_clnt *); > > +void rpc_clnt_show_stats(struct seq_file *, struct rpc_clnt *); > > void rpc_free_iostats(struct rpc_iostats *); > > > > #else /* CONFIG_PROC_FS */ > > @@ -95,7 +95,7 @@ static inline void rpc_count_iostats_metrics(const struct rpc_task *task, > > { > > } > > > > -static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {} > > +static inline void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt) {} > > static inline void rpc_free_iostats(struct rpc_iostats *stats) {} > > > > #endif /* CONFIG_PROC_FS */ > > diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c > > index 32adddd7fb78..2c9453465c78 100644 > > --- a/net/sunrpc/stats.c > > +++ b/net/sunrpc/stats.c > > @@ -235,13 +235,12 @@ static void _print_rpc_iostats(struct seq_file *seq, struct rpc_iostats *stats, > > ktime_to_ms(stats->om_execute)); > > } > > > > -void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) > > +void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt) > > { > > - struct rpc_iostats *stats = clnt->cl_metrics; > > struct rpc_xprt *xprt; > > unsigned int op, maxproc = clnt->cl_maxproc; > > > > - if (!stats) > > + if (!clnt->cl_metrics) > > return; > > > > seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS); > > @@ -256,10 +255,18 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) > > > > seq_printf(seq, "\tper-op statistics\n"); > > for (op = 0; op < maxproc; op++) { > > - _print_rpc_iostats(seq, &stats[op], op, clnt->cl_procinfo); > > + struct rpc_iostats stats = { 0 }; > > + struct rpc_clnt *next = clnt; > > + do { > > + _add_rpc_iostats(&stats, &next->cl_metrics[op]); > > + if (next == next->cl_parent) > > + break; > > + next = next->cl_parent; > > + } while (next); > > + _print_rpc_iostats(seq, &stats, op, clnt->cl_procinfo); > > } > > } > > -EXPORT_SYMBOL_GPL(rpc_print_iostats); > > +EXPORT_SYMBOL_GPL(rpc_clnt_show_stats); > > > > /* > > * Register/unregister RPC proc files > > -- > > 2.14.3 > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > > the body of a message to majordomo@xxxxxxxxxxxxxxx > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- > Chuck Lever > > > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html