linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] NFS: include filelayout DS rpc stats in mountstats
@ 2012-02-13 22:22 Weston Andros Adamson
  2012-02-16 19:48 ` Myklebust, Trond
  0 siblings, 1 reply; 23+ messages in thread
From: Weston Andros Adamson @ 2012-02-13 22:22 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Weston Andros Adamson

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

Signed-off-by: Weston Andros Adamson <dros@netapp.com>
---
Cleaned up version after comments from Trond.  This patch accumulates 
reads, writes and commits (the only DS operations) on the rpc_iostats of 
the nfs_server associated with the mount.

I was confused last week about where we breaking counting stats only for a 
mountpoint -- What I was seeing was two mounts sharing stats if they were the
same server AND the same filesystem on the server.  This patch does not address
that issue.

This patch still counts DS operations on the DS::nfs_client::rpc_clnt's stats
structures.  Assuming this patch is OK, I plan on submitting a patch that will 
show MDS-only and individual DS stats somewhere in /proc/fs/nfsfs/.

 fs/nfs/nfs4filelayout.c        |   19 +++++++++++++++++++
 include/linux/sunrpc/metrics.h |    6 ++++--
 include/linux/sunrpc/sched.h   |    1 +
 net/sunrpc/stats.c             |    8 ++++----
 net/sunrpc/xprt.c              |    5 ++++-
 5 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 79be7ac..47e8f34 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"
 
@@ -189,6 +191,13 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data)
 	rdata->mds_ops->rpc_call_done(task, data);
 }
 
+static void filelayout_read_count_stats(struct rpc_task *task, void *data)
+{
+	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
+
+	rpc_count_iostats(task, NFS_SERVER(rdata->inode)->client->cl_metrics);
+}
+
 static void filelayout_read_release(void *data)
 {
 	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
@@ -268,6 +277,13 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data)
 	wdata->mds_ops->rpc_call_done(task, data);
 }
 
+static void filelayout_write_count_stats(struct rpc_task *task, void *data)
+{
+	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+	rpc_count_iostats(task, NFS_SERVER(wdata->inode)->client->cl_metrics);
+}
+
 static void filelayout_write_release(void *data)
 {
 	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
@@ -288,18 +304,21 @@ static void filelayout_commit_release(void *data)
 struct rpc_call_ops filelayout_read_call_ops = {
 	.rpc_call_prepare = filelayout_read_prepare,
 	.rpc_call_done = filelayout_read_call_done,
+	.rpc_count_stats = filelayout_read_count_stats,
 	.rpc_release = filelayout_read_release,
 };
 
 struct rpc_call_ops filelayout_write_call_ops = {
 	.rpc_call_prepare = filelayout_write_prepare,
 	.rpc_call_done = filelayout_write_call_done,
+	.rpc_count_stats = filelayout_write_count_stats,
 	.rpc_release = filelayout_write_release,
 };
 
 struct rpc_call_ops filelayout_commit_call_ops = {
 	.rpc_call_prepare = filelayout_write_prepare,
 	.rpc_call_done = filelayout_write_call_done,
+	.rpc_count_stats = filelayout_write_count_stats,
 	.rpc_release = filelayout_commit_release,
 };
 
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index b6edbc0..1565bbe 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -74,14 +74,16 @@ struct rpc_clnt;
 #ifdef CONFIG_PROC_FS
 
 struct rpc_iostats *	rpc_alloc_iostats(struct rpc_clnt *);
-void			rpc_count_iostats(struct rpc_task *);
+void			rpc_count_iostats(const struct rpc_task *,
+					  struct rpc_iostats *);
 void			rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
 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_count_iostats(const struct rpc_task *task,
+				     struct rpc_iostats *stats) {}
 static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
 static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
 
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 22dfc24..dc0c3cc 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -103,6 +103,7 @@ typedef void			(*rpc_action)(struct rpc_task *);
 struct rpc_call_ops {
 	void (*rpc_call_prepare)(struct rpc_task *, void *);
 	void (*rpc_call_done)(struct rpc_task *, void *);
+	void (*rpc_count_stats)(struct rpc_task *, void *);
 	void (*rpc_release)(void *);
 };
 
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 3c4f688..1eb3304 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -133,20 +133,19 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);
 /**
  * rpc_count_iostats - tally up per-task stats
  * @task: completed rpc_task
+ * @stats: array of stat structures
  *
  * Relies on the caller for serialization.
  */
-void rpc_count_iostats(struct rpc_task *task)
+void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
 {
 	struct rpc_rqst *req = task->tk_rqstp;
-	struct rpc_iostats *stats;
 	struct rpc_iostats *op_metrics;
 	ktime_t delta;
 
-	if (!task->tk_client || !task->tk_client->cl_metrics || !req)
+	if (!stats || !req)
 		return;
 
-	stats = task->tk_client->cl_metrics;
 	op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
 
 	op_metrics->om_ops++;
@@ -164,6 +163,7 @@ void rpc_count_iostats(struct rpc_task *task)
 	delta = ktime_sub(ktime_get(), task->tk_start);
 	op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta);
 }
+EXPORT_SYMBOL_GPL(rpc_count_iostats);
 
 static void _print_name(struct seq_file *seq, unsigned int op,
 			struct rpc_procinfo *procs)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index efe5495..ab7a28f 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1132,7 +1132,10 @@ void xprt_release(struct rpc_task *task)
 		return;
 
 	xprt = req->rq_xprt;
-	rpc_count_iostats(task);
+	if (task->tk_client)
+		rpc_count_iostats(task, task->tk_client->cl_metrics);
+	if (task->tk_ops->rpc_count_stats != NULL)
+		task->tk_ops->rpc_count_stats(task, task->tk_calldata);
 	spin_lock_bh(&xprt->transport_lock);
 	xprt->ops->release_xprt(xprt, task);
 	if (xprt->ops->release_request)
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread
* [PATCH] NFS: include filelayout DS rpc stats in mountstats
@ 2012-02-17 18:15 Weston Andros Adamson
  2012-02-17 18:47 ` Myklebust, Trond
  0 siblings, 1 reply; 23+ messages in thread
From: Weston Andros Adamson @ 2012-02-17 18:15 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Weston Andros Adamson

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

Signed-off-by: Weston Andros Adamson <dros@netapp.com>
---
Update: don't increment tk_client stats if callback is used.

This still checks task->tk_client != NULL -- I'm not convinced it's unneeded
as it existed in rpc_count_iostats.

 fs/nfs/nfs4filelayout.c        |   19 +++++++++++++++++++
 include/linux/sunrpc/metrics.h |    6 ++++--
 include/linux/sunrpc/sched.h   |    1 +
 net/sunrpc/stats.c             |    8 ++++----
 net/sunrpc/xprt.c              |    5 ++++-
 5 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 79be7ac..47e8f34 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"
 
@@ -189,6 +191,13 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data)
 	rdata->mds_ops->rpc_call_done(task, data);
 }
 
+static void filelayout_read_count_stats(struct rpc_task *task, void *data)
+{
+	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
+
+	rpc_count_iostats(task, NFS_SERVER(rdata->inode)->client->cl_metrics);
+}
+
 static void filelayout_read_release(void *data)
 {
 	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
@@ -268,6 +277,13 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data)
 	wdata->mds_ops->rpc_call_done(task, data);
 }
 
+static void filelayout_write_count_stats(struct rpc_task *task, void *data)
+{
+	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+	rpc_count_iostats(task, NFS_SERVER(wdata->inode)->client->cl_metrics);
+}
+
 static void filelayout_write_release(void *data)
 {
 	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
@@ -288,18 +304,21 @@ static void filelayout_commit_release(void *data)
 struct rpc_call_ops filelayout_read_call_ops = {
 	.rpc_call_prepare = filelayout_read_prepare,
 	.rpc_call_done = filelayout_read_call_done,
+	.rpc_count_stats = filelayout_read_count_stats,
 	.rpc_release = filelayout_read_release,
 };
 
 struct rpc_call_ops filelayout_write_call_ops = {
 	.rpc_call_prepare = filelayout_write_prepare,
 	.rpc_call_done = filelayout_write_call_done,
+	.rpc_count_stats = filelayout_write_count_stats,
 	.rpc_release = filelayout_write_release,
 };
 
 struct rpc_call_ops filelayout_commit_call_ops = {
 	.rpc_call_prepare = filelayout_write_prepare,
 	.rpc_call_done = filelayout_write_call_done,
+	.rpc_count_stats = filelayout_write_count_stats,
 	.rpc_release = filelayout_commit_release,
 };
 
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index b6edbc0..1565bbe 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -74,14 +74,16 @@ struct rpc_clnt;
 #ifdef CONFIG_PROC_FS
 
 struct rpc_iostats *	rpc_alloc_iostats(struct rpc_clnt *);
-void			rpc_count_iostats(struct rpc_task *);
+void			rpc_count_iostats(const struct rpc_task *,
+					  struct rpc_iostats *);
 void			rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
 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_count_iostats(const struct rpc_task *task,
+				     struct rpc_iostats *stats) {}
 static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
 static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
 
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 22dfc24..dc0c3cc 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -103,6 +103,7 @@ typedef void			(*rpc_action)(struct rpc_task *);
 struct rpc_call_ops {
 	void (*rpc_call_prepare)(struct rpc_task *, void *);
 	void (*rpc_call_done)(struct rpc_task *, void *);
+	void (*rpc_count_stats)(struct rpc_task *, void *);
 	void (*rpc_release)(void *);
 };
 
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 3c4f688..1eb3304 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -133,20 +133,19 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);
 /**
  * rpc_count_iostats - tally up per-task stats
  * @task: completed rpc_task
+ * @stats: array of stat structures
  *
  * Relies on the caller for serialization.
  */
-void rpc_count_iostats(struct rpc_task *task)
+void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)
 {
 	struct rpc_rqst *req = task->tk_rqstp;
-	struct rpc_iostats *stats;
 	struct rpc_iostats *op_metrics;
 	ktime_t delta;
 
-	if (!task->tk_client || !task->tk_client->cl_metrics || !req)
+	if (!stats || !req)
 		return;
 
-	stats = task->tk_client->cl_metrics;
 	op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
 
 	op_metrics->om_ops++;
@@ -164,6 +163,7 @@ void rpc_count_iostats(struct rpc_task *task)
 	delta = ktime_sub(ktime_get(), task->tk_start);
 	op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta);
 }
+EXPORT_SYMBOL_GPL(rpc_count_iostats);
 
 static void _print_name(struct seq_file *seq, unsigned int op,
 			struct rpc_procinfo *procs)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index efe5495..100b469 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1132,7 +1132,10 @@ void xprt_release(struct rpc_task *task)
 		return;
 
 	xprt = req->rq_xprt;
-	rpc_count_iostats(task);
+	if (task->tk_ops->rpc_count_stats != NULL)
+		task->tk_ops->rpc_count_stats(task, task->tk_calldata);
+	else if (task->tk_client)
+		rpc_count_iostats(task, task->tk_client->cl_metrics);
 	spin_lock_bh(&xprt->transport_lock);
 	xprt->ops->release_xprt(xprt, task);
 	if (xprt->ops->release_request)
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread
* [PATCH] NFS: include filelayout DS rpc stats in mountstats
@ 2012-02-09 16:41 Weston Andros Adamson
  2012-02-09 16:49 ` Chuck Lever
  2012-02-09 18:16 ` Myklebust, Trond
  0 siblings, 2 replies; 23+ messages in thread
From: Weston Andros Adamson @ 2012-02-09 16:41 UTC (permalink / raw)
  To: Trond.Myklebust, chuck.lever; +Cc: linux-nfs, Weston Andros Adamson

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


^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2012-02-17 19:16 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-13 22:22 [PATCH] NFS: include filelayout DS rpc stats in mountstats 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
  -- strict thread matches above, loose matches on Subject: below --
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
2012-02-09 16:41 Weston Andros Adamson
2012-02-09 16:49 ` 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

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).