linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Banks <gnb@sgi.com>
To: "J. Bruce Fields" <bfields@fieldses.org>
Cc: Linux NFS ML <linux-nfs@vger.kernel.org>
Subject: [patch 05/29] knfsd: Infrastructure for providing stats to userspace
Date: Wed, 01 Apr 2009 07:28:05 +1100	[thread overview]
Message-ID: <20090331202939.751001000@sgi.com> (raw)
In-Reply-To: 20090331202800.739621000@sgi.com

Added iteration and seq_file infrastructure to allow implementing
a /proc file which exports all the entries in a stats hashtable as
text to userspace.  Function nfsd_stats_open() is called in the /proc
file's open method and handles all the subsequent details.

Like all RPC statistics, the format is designed to be easy to parse
in shell scripts and C code.  Counter values are presented in text
form, grouped into lines which start with a two-letter keyword.
For example, the line "by 2680 487656" shows that 2680 bytes of NFS
calls have been received and 487656 bytes of replies have been sent.
The special "nm" keyword starts a new entry and shows it's internal
name, e.g. "nm 192.168.67.45" in the per-client statistics file will
begin the entry for the client whose IP address is 192.168.67.45.

Signed-off-by: Greg Banks <gnb@sgi.com>
---

 fs/nfsd/stats.c            |  173 ++++++++++++++++++++++++++++++++++
 include/linux/nfsd/stats.h |   11 ++
 2 files changed, 184 insertions(+)

Index: bfields/fs/nfsd/stats.c
===================================================================
--- bfields.orig/fs/nfsd/stats.c
+++ bfields/fs/nfsd/stats.c
@@ -426,6 +426,179 @@ void nfsd_stats_post(struct svc_rqst *rq
 }
 
 
+static nfsd_stats_hentry_t *nfsd_stats_hiter_first(nfsd_stats_hiter_t *itr)
+{
+	for (itr->bucket = 0 ;
+	     itr->bucket < itr->sh->sh_size ;
+	     itr->bucket++) {
+		struct hlist_head *hh = &itr->sh->sh_hash[itr->bucket];
+		if (hh->first != NULL)
+			return hentry_from_hnode(hh->first);
+	}
+	return NULL;
+}
+
+static nfsd_stats_hentry_t *nfsd_stats_hiter_next(nfsd_stats_hiter_t *itr,
+						  nfsd_stats_hentry_t *se)
+{
+	struct hlist_head *hh;
+
+	for (;;) {
+		if (se->se_node.next != NULL)
+			return hentry_from_hnode(se->se_node.next);
+		if (++itr->bucket >= itr->sh->sh_size)
+			return NULL;	/* finished iterating */
+		hh = &itr->sh->sh_hash[itr->bucket];
+		if (hh->first != NULL)
+			return hentry_from_hnode(hh->first);
+	}
+}
+
+static nfsd_stats_hentry_t *nfsd_stats_hiter_seek(nfsd_stats_hiter_t *itr,
+						  loff_t pos)
+{
+	nfsd_stats_hentry_t *se;
+
+	for (se = nfsd_stats_hiter_first(itr) ;
+	     se != NULL ;
+	     se = nfsd_stats_hiter_next(itr, se)) {
+		if (!--pos)
+			return se;
+	}
+	return NULL;
+}
+
+static void *nfsd_stats_start(struct seq_file *m, loff_t *pos)
+{
+	nfsd_stats_hiter_t *itr = m->private;
+
+	dprintk("nfsd_stats_start, *pos=%d\n", (int)*pos);
+	down_read(&itr->sh->sh_sem);
+
+	if (!*pos)
+		return SEQ_START_TOKEN;
+
+	return nfsd_stats_hiter_seek(itr, *pos);
+}
+
+static void *nfsd_stats_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	nfsd_stats_hiter_t *itr = m->private;
+	nfsd_stats_hentry_t *se = p;
+
+	dprintk("nfsd_stats_next, *pos=%llu bucket=%d\n", *pos, itr->bucket);
+
+	if (p == SEQ_START_TOKEN)
+		se = nfsd_stats_hiter_first(itr);
+	else
+		se = nfsd_stats_hiter_next(itr, se);
+	++*pos;
+	return se;
+}
+
+static void nfsd_stats_stop(struct seq_file *m, void *p)
+{
+	nfsd_stats_hiter_t *itr = m->private;
+
+	up_read(&itr->sh->sh_sem);
+}
+
+static int nfsd_stats_show(struct seq_file *m, void *p)
+{
+	nfsd_stats_hentry_t *se = p;
+	struct nfsd_op_stats *os = &se->se_data;
+	int i;
+
+	if (p == SEQ_START_TOKEN) {
+		seq_puts(m, "# Version 1.0\n");
+		return 0;
+	}
+
+	dprintk("nfsd_stats_show %s\n",  se->se_name);
+
+	seq_puts(m, "nm ");
+	seq_escape(m, se->se_name, " \t\n\\");
+	seq_printf(m, "\n");
+
+	/* histogram of operations */
+	seq_puts(m, "op");
+	for (i = 0 ; i < NFSD_STATS_OP_NUM ; i++)
+		seq_printf(m, " %lu", os->os_ops[i]);
+	seq_putc(m, '\n');
+
+	/* bytes in and out */
+	seq_printf(m, "by %lu %lu\n", os->os_bytes_in, os->os_bytes_out);
+
+	/* histogram of read sizes */
+	seq_puts(m, "rs");
+	for (i = 0 ; i < NFSD_STATS_SIZE_NUM ; i++)
+		seq_printf(m, " %lu", os->os_read_sizes[i]);
+	seq_putc(m, '\n');
+
+	/* histogram of write sizes */
+	seq_puts(m, "ws");
+	for (i = 0 ; i < NFSD_STATS_SIZE_NUM ; i++)
+		seq_printf(m, " %lu", os->os_write_sizes[i]);
+	seq_putc(m, '\n');
+
+	/* counts of operations by transport */
+	seq_printf(m, "tr udp %lu\n",
+		   os->os_transports[NFSD_STATS_TRANSPORT_UDP]);
+	seq_printf(m, "tr tcp %lu\n",
+		   os->os_transports[NFSD_STATS_TRANSPORT_TCP]);
+#if defined(CONFIG_NFSD_RDMA) || defined(CONFIG_NFSD_RDMA_MODULE)
+	seq_printf(m, "tr rdma %lu\n",
+		   os->os_transports[NFSD_STATS_TRANSPORT_RDMA]);
+#endif
+
+	/* counts of operations by version */
+	seq_printf(m, "ve 2 %lu\n",
+		   os->os_versions[NFSD_STATS_VERSION_V2]);
+	seq_printf(m, "ve 3 %lu\n",
+		   os->os_versions[NFSD_STATS_VERSION_V3]);
+	seq_printf(m, "ve 4 %lu\n",
+		   os->os_versions[NFSD_STATS_VERSION_V4]);
+
+	/* histogram of service times */
+	seq_puts(m, "st");
+	for (i = 0 ; i < NFSD_STATS_SVCTIME_NUM ; i++)
+		seq_printf(m, " %lu", os->os_service_times[i]);
+	seq_putc(m, '\n');
+
+	return 0;
+}
+
+static struct seq_operations nfsd_stats_seq_ops = {
+	.start	= nfsd_stats_start,
+	.next	= nfsd_stats_next,
+	.stop	= nfsd_stats_stop,
+	.show	= nfsd_stats_show,
+};
+
+int nfsd_stats_open(struct file *file, nfsd_stats_hash_t *sh)
+{
+	int err;
+	nfsd_stats_hiter_t *itr;
+
+	if (sh->sh_hash == NULL)
+		return -ENOENT;
+
+	if ((itr = kmalloc(sizeof(*itr), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	if ((err = seq_open(file, &nfsd_stats_seq_ops))) {
+		kfree(itr);
+		return err;
+	}
+
+	itr->sh = sh;
+	itr->bucket = 0;
+	((struct seq_file *) file->private_data)->private = itr;
+
+	return 0;
+}
+
+
 void
 nfsd_stat_init(void)
 {
Index: bfields/include/linux/nfsd/stats.h
===================================================================
--- bfields.orig/include/linux/nfsd/stats.h
+++ bfields/include/linux/nfsd/stats.h
@@ -100,6 +100,7 @@ struct nfsd_op_stats {
 
 typedef struct nfsd_stats_hash		nfsd_stats_hash_t;
 typedef struct nfsd_stats_hentry	nfsd_stats_hentry_t;
+typedef struct nfsd_stats_hiter		nfsd_stats_hiter_t;
 
 /* Entry in the export and client stats hashtables */
 struct nfsd_stats_hentry {
@@ -125,6 +126,13 @@ struct nfsd_stats_hash {
 	struct timer_list	sh_prune_timer;
 };
 
+/* Hashtable iteration state used during seq_file traversal */
+struct nfsd_stats_hiter {
+	nfsd_stats_hash_t *sh;
+	int bucket;
+};
+
+
 extern struct nfsd_stats	nfsdstats;
 extern struct svc_stat		nfsd_svcstats;
 
@@ -192,6 +200,9 @@ void nfsd_stats_pre(struct svc_rqst *rqs
 /* nfsd calls this after servicing a request */
 void nfsd_stats_post(struct svc_rqst *rqstp);
 
+/* open the hash for a seq_file pass to userspace */
+int nfsd_stats_open(struct file *file, nfsd_stats_hash_t *sh);
+
 
 
 

--
Greg

  parent reply	other threads:[~2009-03-31 21:02 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-31 20:28 [patch 00/29] SGI enhancedNFS patches Greg Banks
2009-03-31 20:28 ` [patch 01/29] knfsd: Add infrastructure for measuring RPC service times Greg Banks
2009-04-25  2:13   ` J. Bruce Fields
2009-04-25  2:14     ` J. Bruce Fields
2009-04-25  2:52     ` Greg Banks
2009-03-31 20:28 ` [patch 02/29] knfsd: Add stats table infrastructure Greg Banks
2009-04-25  3:56   ` J. Bruce Fields
2009-04-26  4:12     ` Greg Banks
2009-03-31 20:28 ` [patch 03/29] knfsd: add userspace controls for stats tables Greg Banks
2009-04-25 21:57   ` J. Bruce Fields
2009-04-25 22:03     ` J. Bruce Fields
2009-04-27 16:06       ` Chuck Lever
2009-04-27 23:22         ` J. Bruce Fields
2009-04-28 15:37           ` Chuck Lever
2009-04-28 15:57             ` J. Bruce Fields
2009-04-28 16:03               ` Chuck Lever
2009-04-28 16:26                 ` J. Bruce Fields
2009-04-29  1:45               ` Greg Banks
     [not found]         ` <ac442c870904271827w6041a67ew82fe36a843beeac3@mail.gmail.com>
     [not found]           ` <ac442c870904271827w6041a67ew82fe36a843beeac3-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-04-28  1:31             ` Greg Banks
2009-04-26  4:14     ` Greg Banks
2009-03-31 20:28 ` [patch 04/29] knfsd: Add stats updating API Greg Banks
2009-03-31 20:28 ` Greg Banks [this message]
2009-04-01  0:28   ` [patch 05/29] knfsd: Infrastructure for providing stats to userspace J. Bruce Fields
2009-04-01  3:43     ` Greg Banks
2009-03-31 20:28 ` [patch 06/29] knfsd: Gather per-export stats Greg Banks
2009-03-31 20:28 ` [patch 07/29] knfsd: Prefetch the per-export stats entry Greg Banks
2009-03-31 20:28 ` [patch 08/29] knfsd: Gather per-client stats Greg Banks
2009-03-31 20:28 ` [patch 09/29] knfsd: Cache per-client stats entry on TCP transports Greg Banks
2009-03-31 20:28 ` [patch 10/29] knfsd: Update per-client & per-export stats from NFSv3 Greg Banks
2009-03-31 20:28 ` [patch 11/29] knfsd: Update per-client & per-export stats from NFSv2 Greg Banks
2009-03-31 20:28 ` [patch 12/29] knfsd: Update per-client & per-export stats from NFSv4 Greg Banks
2009-03-31 20:28 ` [patch 13/29] knfsd: reply cache cleanups Greg Banks
2009-05-12 19:54   ` J. Bruce Fields
2009-03-31 20:28 ` [patch 14/29] knfsd: better hashing in the reply cache Greg Banks
2009-05-08 22:01   ` J. Bruce Fields
2009-03-31 20:28 ` [patch 15/29] knfsd: fix reply cache memory corruption Greg Banks
2009-05-12 19:55   ` J. Bruce Fields
2009-03-31 20:28 ` [patch 16/29] knfsd: use client IPv4 address in reply cache hash Greg Banks
2009-05-11 21:48   ` J. Bruce Fields
2009-03-31 20:28 ` [patch 17/29] knfsd: make the reply cache SMP-friendly Greg Banks
2009-03-31 20:28 ` [patch 18/29] knfsd: dynamically expand the reply cache Greg Banks
2009-05-26 18:57   ` J. Bruce Fields
2009-05-26 19:04     ` J. Bruce Fields
2009-05-26 21:24     ` Rob Gardner
2009-05-26 21:52       ` J. Bruce Fields
2009-05-27  0:28       ` Greg Banks
2009-03-31 20:28 ` [patch 19/29] knfsd: faster probing in " Greg Banks
2009-03-31 20:28 ` [patch 20/29] knfsd: add extended reply cache stats Greg Banks
2009-03-31 20:28 ` [patch 21/29] knfsd: remove unreported filehandle stats counters Greg Banks
2009-05-12 20:00   ` J. Bruce Fields
2009-03-31 20:28 ` [patch 22/29] knfsd: make svc_authenticate() scale Greg Banks
2009-05-12 21:24   ` J. Bruce Fields
2009-03-31 20:28 ` [patch 23/29] knfsd: introduce SVC_INC_STAT Greg Banks
2009-03-31 20:28 ` [patch 24/29] knfsd: remove the program field from struct svc_stat Greg Banks
2009-03-31 20:28 ` [patch 25/29] knfsd: allocate svc_serv.sv_stats dynamically Greg Banks
2009-03-31 20:28 ` [patch 26/29] knfsd: make svc_serv.sv_stats per-CPU Greg Banks
2009-03-31 20:28 ` [patch 27/29] knfsd: move hot procedure count field out of svc_procedure Greg Banks
2009-03-31 20:28 ` [patch 28/29] knfsd: introduce NFSD_INC_STAT() Greg Banks
2009-03-31 20:28 ` [patch 29/29] knfsd: make nfsdstats per-CPU Greg Banks
2009-04-01  0:23 ` [patch 00/29] SGI enhancedNFS patches J. Bruce Fields
2009-04-01  3:32   ` Greg Banks
     [not found]     ` <ac442c870903312032t34630c6dvdbb644cb510f8079-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-04-01  6:34       ` Jeff Garzik
2009-04-01  6:41         ` Greg Banks

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=20090331202939.751001000@sgi.com \
    --to=gnb@sgi.com \
    --cc=bfields@fieldses.org \
    --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).