linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Weston Andros Adamson <dros@netapp.com>
To: Trond.Myklebust@netapp.com, chuck.lever@oracle.com
Cc: linux-nfs@vger.kernel.org, Weston Andros Adamson <dros@netapp.com>
Subject: [PATCH] NFS: include filelayout DS rpc stats in mountstats
Date: Thu,  9 Feb 2012 11:41:26 -0500	[thread overview]
Message-ID: <1328805686-19559-1-git-send-email-dros@netapp.com> (raw)

Include RPC statistics from all data servers in /proc/self/mountstats for pNFS
filelayout mounts.

The additional info printed on the "per-op statistics" line does not break
current mountstats(8) from nfs-utils.

Signed-off-by: Weston Andros Adamson <dros@netapp.com>
---

This is clearly a better approach than I was taking trying to keep DS rpc stats
separate in /proc/self/mountstats.

FYI, there are no other callers of rpc_print_iostats().

The new output of /proc/self/mountstats works fine with current mountstats 
userland tool.  The additional data on the per-op statistics line doesn't make
it into the output, but I left it in /proc/self/mountstats because it doesn't
break anything and can be included in newer versions of mountstats.

I plan on adding the per-DS stats (rpc and others) somewhere in /proc/fs/nfsfs/
soon.

 fs/nfs/nfs4filelayout.c        |   30 ++++++++++++++++++++++++++
 fs/nfs/pnfs.h                  |   23 ++++++++++++++++++++
 fs/nfs/pnfs_dev.c              |   45 ++++++++++++++++++++++++++++++++++++++++
 fs/nfs/super.c                 |    3 +-
 include/linux/sunrpc/metrics.h |   13 +++++++++-
 net/sunrpc/stats.c             |   38 ++++++++++++++++++++++++++++++++-
 6 files changed, 147 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 79be7ac..51c71e5 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -33,6 +33,8 @@
 #include <linux/nfs_page.h>
 #include <linux/module.h>
 
+#include <linux/sunrpc/metrics.h>
+
 #include "internal.h"
 #include "nfs4filelayout.h"
 
@@ -918,6 +920,33 @@ filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d)
 	nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node));
 }
 
+static unsigned int
+filelayout_rpc_add_iostats(struct rpc_iostats *total,
+			   unsigned int maxproc,
+			   struct nfs4_deviceid_node *d)
+{
+	struct nfs4_file_layout_dsaddr *dsaddr;
+	struct nfs4_pnfs_ds *ds;
+	unsigned int num_ds = 0;
+	u32 i;
+
+	dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
+
+	for (i = 0; i < dsaddr->ds_num; i++) {
+		ds = dsaddr->ds_list[i];
+
+		/* only add iostats if nfs_client is different from MDS */
+		if (ds && ds->ds_clp && d->nfs_client != ds->ds_clp) {
+			struct rpc_clnt *clnt = ds->ds_clp->cl_rpcclient;
+			rpc_add_iostats(total, clnt->cl_metrics,
+					min(maxproc, clnt->cl_maxproc));
+			num_ds++;
+		}
+	}
+
+	return num_ds;
+}
+
 static struct pnfs_layoutdriver_type filelayout_type = {
 	.id			= LAYOUT_NFSV4_1_FILES,
 	.name			= "LAYOUT_NFSV4_1_FILES",
@@ -932,6 +961,7 @@ static struct pnfs_layoutdriver_type filelayout_type = {
 	.read_pagelist		= filelayout_read_pagelist,
 	.write_pagelist		= filelayout_write_pagelist,
 	.free_deviceid_node	= filelayout_free_deveiceid_node,
+	.ds_rpc_add_iostats	= filelayout_rpc_add_iostats,
 };
 
 static int __init nfs4filelayout_init(void)
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 53d593a..d1b82eb 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -72,6 +72,7 @@ enum layoutdriver_policy_flags {
 };
 
 struct nfs4_deviceid_node;
+struct rpc_iostats;
 
 /* Per-layout driver specific registration structure */
 struct pnfs_layoutdriver_type {
@@ -119,6 +120,9 @@ struct pnfs_layoutdriver_type {
 	void (*encode_layoutcommit) (struct pnfs_layout_hdr *layoutid,
 				     struct xdr_stream *xdr,
 				     const struct nfs4_layoutcommit_args *args);
+
+	unsigned int (*ds_rpc_add_iostats) (struct rpc_iostats *, unsigned int,
+					    struct nfs4_deviceid_node *);
 };
 
 struct pnfs_layout_hdr {
@@ -239,6 +243,10 @@ void nfs4_init_deviceid_node(struct nfs4_deviceid_node *,
 struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *);
 bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
 void nfs4_deviceid_purge_client(const struct nfs_client *);
+void nfs4_deviceid_rpc_print_iostats(struct seq_file *seq,
+				     const struct nfs_client *clp,
+				     const struct pnfs_layoutdriver_type *ld);
+
 
 static inline int lo_fail_bit(u32 iomode)
 {
@@ -328,6 +336,15 @@ static inline int pnfs_return_layout(struct inode *ino)
 	return 0;
 }
 
+static inline int
+pnfs_rpc_print_iostats(struct seq_file *m, struct nfs_server *nfss)
+{
+	if (!pnfs_enabled_sb(nfss))
+		return 0;
+	nfs4_deviceid_rpc_print_iostats(m, nfss->nfs_client,
+					nfss->pnfs_curr_ld);
+	return 1;
+}
 #else  /* CONFIG_NFS_V4_1 */
 
 static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
@@ -429,6 +446,12 @@ static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync)
 static inline void nfs4_deviceid_purge_client(struct nfs_client *ncl)
 {
 }
+
+static inline void
+pnfs_rpc_print_iostats(struct seq_file *m, struct nfs_server *nfss)
+{
+	return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 #endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index 4f359d2..aa5d102 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -29,6 +29,9 @@
  */
 
 #include <linux/export.h>
+
+#include <linux/sunrpc/metrics.h>
+
 #include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PNFS
@@ -115,6 +118,48 @@ nfs4_find_get_deviceid(const struct pnfs_layoutdriver_type *ld,
 }
 EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid);
 
+
+void
+nfs4_deviceid_rpc_print_iostats(struct seq_file *seq,
+				const struct nfs_client *clp,
+				const struct pnfs_layoutdriver_type *ld)
+{
+	struct nfs4_deviceid_node *d;
+	struct hlist_node *n;
+	struct rpc_iostats *totals;
+	char msgbuf[64];
+	unsigned int num_ds = 0;
+	unsigned int maxproc;
+	long h;
+
+	if (!ld->ds_rpc_add_iostats)
+		return;
+	totals = rpc_alloc_iostats(clp->cl_rpcclient);
+	if (!totals)
+		return;
+	maxproc = clp->cl_rpcclient->cl_maxproc;
+	rpc_add_iostats(totals, clp->cl_rpcclient->cl_metrics, maxproc);
+
+	rcu_read_lock();
+	for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) {
+		hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[h], node) {
+			if (d->ld == ld && d->nfs_client == clp) {
+				if (atomic_read(&d->ref))
+					num_ds += ld->ds_rpc_add_iostats(totals,
+							maxproc, d);
+			}
+		}
+	}
+	rcu_read_unlock();
+
+	snprintf(msgbuf, sizeof(msgbuf),
+		 " for the metadata server and %u data server%s", num_ds,
+		 (num_ds != 1) ? "s" : "");
+	rpc_print_iostats(seq, clp->cl_rpcclient, totals, msgbuf);
+	rpc_free_iostats(totals);
+}
+EXPORT_SYMBOL_GPL(nfs4_deviceid_rpc_print_iostats);
+
 /*
  * Remove a deviceid from cache
  *
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d18a90b..76d0850 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -870,7 +870,8 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root)
 #endif
 	seq_printf(m, "\n");
 
-	rpc_print_iostats(m, nfss->client);
+	if (!pnfs_rpc_print_iostats(m, nfss))
+		rpc_print_iostats(m, nfss->client, NULL, NULL);
 
 	return 0;
 }
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index b6edbc0..e6e04e4 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -75,14 +75,23 @@ struct rpc_clnt;
 
 struct rpc_iostats *	rpc_alloc_iostats(struct rpc_clnt *);
 void			rpc_count_iostats(struct rpc_task *);
-void			rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
+void			rpc_print_iostats(struct seq_file *,
+					  struct rpc_clnt *,
+					  struct rpc_iostats *,
+					  const char *);
+void			rpc_add_iostats(struct rpc_iostats *,
+					struct rpc_iostats *, unsigned int);
 void			rpc_free_iostats(struct rpc_iostats *);
 
 #else  /*  CONFIG_PROC_FS  */
 
 static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
 static inline void rpc_count_iostats(struct rpc_task *task) {}
-static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_print_iostats(struct seq_file *seq,
+				     struct rpc_iostats *stat) {}
+static inline void rpc_add_iostats(struct rpc_iostats *total,
+				   struct rpc_iostats *new,
+				   unsigned int maxproc) {}
 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 3c4f688..342df57 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -176,12 +176,16 @@ static void _print_name(struct seq_file *seq, unsigned int op,
 		seq_printf(seq, "\t%12u: ", op);
 }
 
-void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
+void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt,
+		       struct rpc_iostats *altstats,
+		       const char *altstats_msg)
 {
 	struct rpc_iostats *stats = clnt->cl_metrics;
 	struct rpc_xprt *xprt = clnt->cl_xprt;
 	unsigned int op, maxproc = clnt->cl_maxproc;
 
+	if (altstats)
+		stats = altstats;
 	if (!stats)
 		return;
 
@@ -192,7 +196,8 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
 	if (xprt)
 		xprt->ops->print_stats(xprt, seq);
 
-	seq_printf(seq, "\tper-op statistics\n");
+	seq_printf(seq, "\tper-op statistics%s\n",
+		   (altstats && altstats_msg) ? altstats_msg : "");
 	for (op = 0; op < maxproc; op++) {
 		struct rpc_iostats *metrics = &stats[op];
 		_print_name(seq, op, clnt->cl_procinfo);
@@ -209,6 +214,35 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
 }
 EXPORT_SYMBOL_GPL(rpc_print_iostats);
 
+void
+rpc_add_iostats(struct rpc_iostats *totals, struct rpc_iostats *new,
+		unsigned int maxproc)
+{
+	unsigned int op;
+
+	for (op = 0; op < maxproc; op++) {
+		struct rpc_iostats *op_totals = &totals[op],
+				   *op_new = &new[op];
+
+		op_totals->om_ops += op_new->om_ops;
+		op_totals->om_ntrans += op_new->om_ntrans;
+		op_totals->om_timeouts += op_new->om_timeouts;
+
+		op_totals->om_bytes_sent += op_new->om_bytes_sent;
+		op_totals->om_bytes_recv += op_new->om_bytes_recv;
+
+		op_totals->om_queue = ktime_add(op_totals->om_queue,
+					       op_new->om_queue);
+
+		op_totals->om_rtt = ktime_add(op_totals->om_rtt,
+					      op_new->om_rtt);
+
+		op_totals->om_execute = ktime_add(op_totals->om_execute,
+						 op_new->om_execute);
+	}
+}
+EXPORT_SYMBOL_GPL(rpc_add_iostats);
+
 /*
  * Register/unregister RPC proc files
  */
-- 
1.7.4.4


             reply	other threads:[~2012-02-09 16:41 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-09 16:41 Weston Andros Adamson [this message]
2012-02-09 16:49 ` [PATCH] NFS: include filelayout DS rpc stats in mountstats Chuck Lever
2012-02-09 16:59   ` Adamson, Dros
2012-02-09 18:16 ` Myklebust, Trond
2012-02-09 19:13   ` Adamson, Dros
2012-02-09 19:27     ` Myklebust, Trond
2012-02-09 19:48       ` Adamson, Dros
2012-02-09 19:58         ` Myklebust, Trond
2012-02-09 20:23           ` Adamson, Dros
2012-02-09 20:37             ` Myklebust, Trond
2012-02-09 20:47               ` Adamson, Dros
2012-02-09 20:00         ` Myklebust, Trond
  -- strict thread matches above, loose matches on Subject: below --
2012-02-13 22:22 Weston Andros Adamson
2012-02-16 19:48 ` Myklebust, Trond
2012-02-16 20:44   ` Adamson, Dros
2012-02-16 20:56     ` Adamson, Dros
2012-02-16 21:01     ` Myklebust, Trond
2012-02-16 21:08       ` Adamson, Dros
2012-02-17 18:15 Weston Andros Adamson
2012-02-17 18:47 ` Myklebust, Trond
2012-02-17 19:02   ` Adamson, Dros
2012-02-17 19:04     ` Myklebust, Trond
2012-02-17 19:16       ` Adamson, Dros

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1328805686-19559-1-git-send-email-dros@netapp.com \
    --to=dros@netapp.com \
    --cc=Trond.Myklebust@netapp.com \
    --cc=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).