[rds-commits] zab commits r133 - trunk/linux/net/rds

svn-commits@oss.oracle.com svn-commits at oss.oracle.com
Fri Jul 14 16:37:52 CDT 2006


Author: zab
Date: 2006-07-14 16:37:50 -0500 (Fri, 14 Jul 2006)
New Revision: 133

Added:
   trunk/linux/net/rds/ib_stats.c
Modified:
   trunk/linux/net/rds/Makefile
   trunk/linux/net/rds/af_rds.c
   trunk/linux/net/rds/ib.c
   trunk/linux/net/rds/ib.h
   trunk/linux/net/rds/ib_send.c
   trunk/linux/net/rds/rds.h
   trunk/linux/net/rds/stats.c
   trunk/linux/net/rds/transport.c
Log:
Export stats from /proc/net/rds/stats

Move away from exporting stats through a getsockopt and instead export
ascii stats through a boring /proc file.  Not ideal, but simple and
not surprising.  IB had stats to export and the getsockopt interface didn't
seem quite right for global transport stats.

Perhaps in the future the statistics_() interface can be used.


Modified: trunk/linux/net/rds/Makefile
===================================================================
--- trunk/linux/net/rds/Makefile	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/Makefile	2006-07-14 21:37:50 UTC (rev 133)
@@ -4,4 +4,6 @@
 			recv.o send.o stats.o sysctl.o threads.o transport.o\
 		tcp.o tcp_connect.o tcp_listen.o tcp_send.o tcp_recv.o	\
 		ib.o ib_cm.o ib_recv.o ib_ring.o ib_send.o ib_sysctl.o	\
+		ib.o ib_cm.o ib_recv.o ib_ring.o ib_send.o ib_stats.o	\
+			ib_sysctl.o					\
 		loop.o

Modified: trunk/linux/net/rds/af_rds.c
===================================================================
--- trunk/linux/net/rds/af_rds.c	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/af_rds.c	2006-07-14 21:37:50 UTC (rev 133)
@@ -218,9 +218,6 @@
 		goto out;
 
 	switch(optname) {
-		case RDS_STATS_GLOBAL:
-			ret = rds_stats_get(optname, optval, optlen);
-			break;
 		default:
 			break;
 	}
@@ -230,7 +227,6 @@
 
 }
 
-
 static int rds_connect(struct socket *sock, struct sockaddr *uaddr,
 		       int addr_len, int flags)
 {
@@ -390,6 +386,7 @@
 	rds_trans_exit();
 	rds_sysctl_exit();
 	rds_threads_exit();
+	rds_stats_exit();
 }
 module_exit(rds_exit);
 
@@ -423,9 +420,12 @@
 	ret = rds_sysctl_init();
 	if (ret)
 		goto out_trans;
+	ret = rds_stats_init();
+	if (ret)
+		goto out_sysctl;
 	ret = proto_register(&rds_proto, 0);
 	if (ret)
-		goto out_sysctl;
+		goto out_stats;
 	ret = sock_register(&rds_family_ops);
 	if (ret)
 		goto out_proto;
@@ -434,6 +434,8 @@
 
 out_proto:
 	proto_unregister(&rds_proto);
+out_stats:
+	rds_stats_exit();
 out_sysctl:
 	rds_sysctl_exit();
 out_trans:

Modified: trunk/linux/net/rds/ib.c
===================================================================
--- trunk/linux/net/rds/ib.c	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/ib.c	2006-07-14 21:37:50 UTC (rev 133)
@@ -68,6 +68,7 @@
 	.inc_process_acks	= rds_ib_inc_process_acks,
 	.listen_stop		= rds_ib_listen_stop,
 	.ack_queue_inc		= rds_ack_queue_inc,
+	.print_stats		= rds_ib_print_stats,
 };
 
 int __init rds_ib_init(void)

Modified: trunk/linux/net/rds/ib.h
===================================================================
--- trunk/linux/net/rds/ib.h	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/ib.h	2006-07-14 21:37:50 UTC (rev 133)
@@ -72,6 +72,10 @@
 	struct rds_ib_recv_work *i_recvs;
 };
 
+struct rds_ib_statistics {
+	unsigned long	s_ib_tx_ring_full;
+};
+
 extern struct workqueue_struct *rds_ib_wq;
 
 /* ib.c */
@@ -117,6 +121,11 @@
 void rds_ib_send_init_ring(struct rds_ib_connection *ic);
 void rds_ib_send_clear_ring(struct rds_ib_connection *ic);
 
+/* ib_stats.c */
+DECLARE_PER_CPU(struct rds_ib_statistics, rds_ib_stats);
+#define rds_ib_stats_inc(member) rds_stats_inc_which(rds_ib_stats, member)
+void rds_ib_print_stats(struct seq_file *seq);
+
 /* ib_sysctl.c */
 extern unsigned long rds_ib_sysctl_max_send_wr;
 extern unsigned long rds_ib_sysctl_max_recv_wr;

Modified: trunk/linux/net/rds/ib_send.c
===================================================================
--- trunk/linux/net/rds/ib_send.c	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/ib_send.c	2006-07-14 21:37:50 UTC (rev 133)
@@ -166,6 +166,7 @@
 
 	work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
 	if (work_alloc == 0) {
+		rds_ib_stats_inc(s_ib_tx_ring_full);
 		ret = -EAGAIN;
 		goto out;
 	}

Added: trunk/linux/net/rds/ib_stats.c
===================================================================
--- trunk/linux/net/rds/ib_stats.c	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/ib_stats.c	2006-07-14 21:37:50 UTC (rev 133)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+#include <linux/percpu.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+
+#include "rds.h"
+#include "ib.h"
+
+DEFINE_PER_CPU(struct rds_ib_statistics, rds_ib_stats) ____cacheline_aligned;
+
+void rds_ib_print_stats(struct seq_file *seq)
+{
+	struct rds_ib_statistics stats = {0, };
+	unsigned long *src;
+	unsigned long *sum;
+	size_t i;
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		src = (unsigned long *)&(per_cpu(rds_ib_stats, cpu));
+		sum = (unsigned long *)&stats;
+		for (i = 0; i < sizeof(stats) / sizeof(unsigned long); i++)
+			*(sum++) += *(src++);
+	}
+
+/* :%s/unsigned long\>.*\<s_\(.*\);/S(\1);/g */
+
+#define S(which) seq_printf(seq, rds_stat_fmt, #which, stats.s_##which)
+	S(ib_tx_ring_full);
+#undef S
+}

Modified: trunk/linux/net/rds/rds.h
===================================================================
--- trunk/linux/net/rds/rds.h	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/rds.h	2006-07-14 21:37:50 UTC (rev 133)
@@ -23,7 +23,6 @@
 
 #define RDS_CANCEL_SENT_TO	1
 #define RDS_SNDBUF		2
-#define RDS_STATS_GLOBAL	3
 
 #define RDS_FRAG_SHIFT	12
 #define RDS_FRAG_SIZE	((unsigned int)(1 << RDS_FRAG_SHIFT))
@@ -184,6 +183,7 @@
 	void (*listen_stop)(void);
 	void (*ack_queue_inc)(struct rds_incoming *inc, gfp_t gfp,
 			      enum km_type km);
+	void (*print_stats)(struct seq_file *seq);
 };
 
 struct rds_sock {
@@ -330,11 +330,14 @@
 
 /* stats.c */
 DECLARE_PER_CPU(struct rds_statistics, rds_stats);
-#define rds_stats_inc(member) do {			\
-	per_cpu(rds_stats, get_cpu()).member++;		\
+#define rds_stats_inc_which(which, member) do {		\
+	per_cpu(which, get_cpu()).member++;		\
 	put_cpu();					\
 } while (0)
-int rds_stats_get(int optname, char __user *optval, int __user *optlen);
+#define rds_stats_inc(member) rds_stats_inc_which(rds_stats, member)
+int __init rds_stats_init(void);
+void rds_stats_exit(void);
+extern char *rds_stat_fmt;
 
 /* sysctl.c */
 int __init rds_sysctl_init(void);
@@ -354,6 +357,7 @@
 extern struct rds_transport rds_ib_transport;
 int __init rds_ib_init(void);
 void __exit rds_ib_exit(void);
+extern struct file_operations rds_ib_stats_seq_fops;
 
 /* threads.c */
 int __init rds_threads_init(void);
@@ -368,6 +372,7 @@
 /* transport.c */
 struct rds_transport *rds_trans_get_preferred(__be32 addr);
 void rds_trans_stop_listening(void);
+void rds_trans_print_stats(struct seq_file *seq);
 int __init rds_trans_init(void);
 void __exit rds_trans_exit(void);
 

Modified: trunk/linux/net/rds/stats.c
===================================================================
--- trunk/linux/net/rds/stats.c	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/stats.c	2006-07-14 21:37:50 UTC (rev 133)
@@ -16,84 +16,102 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 021110-1307, USA.
  */
-#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 
 #include "rds.h"
 
+/*
+ * We probably want to remove all this junk and move to the generic
+ * statistic_*() interface once it is merged.  This serves a purpose for now
+ * and at least people won't be surprised by yet another goofy /proc file.
+ */
+
+char *rds_stat_fmt = "%-25s %lu\n";
+
 DEFINE_PER_CPU(struct rds_statistics, rds_stats) ____cacheline_aligned;
+static struct proc_dir_entry *rds_proc_dir = NULL;
 
-/*
- * The user of the stats interface sees RDS_ sockopts which export an array of
- * u64s.  The interface is made back and forwards compatible by only copying as
- * much of the struct as the user asked for in optlen and returning the amount
- * copied.  New stats are only appended.
- *
- * Stats are stored as unsigned longs per-cpu to avoid overhead.  The rare
- * inconsistencies that come from a lack of locking is ok.  For now we'll be
- * surprising as the longs wrap and the u64 sums jump around.  If someone
- * notices we could fix that by suming as stats are incremented and get
- * close to wrapping.
- *
- * Summing a cacheline at a time is a compromise between avoiding allocating an
- * entire stats struct and avoiding the worst case of hitting each cpu for each
- * stat.
- */
-int rds_stats_get(int optname, char __user *optval, int __user *optlen)
+static int rds_stats_seq_show(struct seq_file *seq, void *v)
 {
-	/* scary, but we're high in the stack */
-	u64 dest[L1_CACHE_BYTES / sizeof(u64)];
-	size_t i, cur, elements;
-	int len, ret, cpu, bytes_to_copy, vals_to_copy, copied;
+	struct rds_statistics stats = {0, };
 	unsigned long *src;
+	unsigned long *sum;
+	size_t i;
+	int cpu;
 
-	if (get_user(len, optlen)) {
-		ret = -EFAULT;
-		goto out;
+	for_each_online_cpu(cpu) {
+		src = (unsigned long *)&(per_cpu(rds_stats, cpu));
+		sum = (unsigned long *)&stats;
+		for (i = 0; i < sizeof(stats) / sizeof(unsigned long); i++)
+			*(sum++) += *(src++);
 	}
 
-	if (len < 0) {
-		ret = -ERANGE;
-		goto out;
-	}
+/* :%s/unsigned long\>.*\<s_\(.*\);/S(\1);/g */
 
-	switch(optname) {
-		case RDS_STATS_GLOBAL:
-			elements = sizeof(struct rds_statistics) /
-				   sizeof(unsigned long);
-			break;
-		default:
-			ret = -EINVAL;
-			goto out;
-	}
+#define S(which) seq_printf(seq, rds_stat_fmt, #which, stats.s_##which)
+	S(ack_entry_hit);
+	S(ack_entry_miss);
+	S(ack_message_full);
+	S(ack_message_fast);
+	S(ack_message_deadline);
+	S(ack_message_received);
+	S(ack_alloc_fail);
+	S(conn_reset);
+	S(recv_drop_old_seq);
+	S(recv_drop_no_sock);
+	S(recv_drop_dead_sock);
+	S(recv_deliver_raced);
+	S(recv_delivered);
+	S(recv_queued);
+	S(send_queue_full);
+#undef S
 
-	cur = 0;
-	copied = 0;
+	rds_trans_print_stats(seq);
 
-	while (copied < len && cur < elements) {
-		/* first sum a block of stats from the cpus */
-		vals_to_copy = min_t(int, ARRAY_SIZE(dest), elements - cur);
-		memset(dest, 0, sizeof(dest));
-		for_each_online_cpu(cpu) {
-			src = (unsigned long *)&(per_cpu(rds_stats, cpu));
-			for (i = 0; i < vals_to_copy; i++)
-				dest[i] += src[cur + i];
-		}
-		cur += vals_to_copy;
+	return 0;
+}
 
-		/* then copy the sums to the user */
-		bytes_to_copy = min_t(int, len - copied, 
-				      vals_to_copy * sizeof(u64));
-		if (copy_to_user(optval + copied, dest, bytes_to_copy)) {
-			ret = -EFAULT;
-			goto out;
-		}
-		copied += bytes_to_copy;
+static int rds_stats_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rds_stats_seq_show, NULL);
+}
+
+static struct file_operations rds_stats_seq_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = rds_stats_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+void rds_stats_exit(void)
+{
+	if (rds_proc_dir) {
+		remove_proc_entry("stats", rds_proc_dir);
+		remove_proc_entry("rds", proc_net);
 	}
+}
 
-	if (put_user(copied, optlen))
-		ret = -EFAULT;
-	else
-		ret = 0;
+int __init rds_stats_init(void)
+{
+	int ret = -ENOMEM;
+	struct proc_dir_entry *ent;
+
+	rds_proc_dir = proc_mkdir("rds", proc_net);
+	if (rds_proc_dir == NULL)
+		goto out;
+
+	ent = create_proc_entry("stats", S_IRUGO, rds_proc_dir);
+	if (ent == NULL)
+		goto out;
+	ent->proc_fops = &rds_stats_seq_fops;
+
+	ret = 0;
+
 out:
+	if (ret)
+		rds_stats_exit();
 	return ret;
 }

Modified: trunk/linux/net/rds/transport.c
===================================================================
--- trunk/linux/net/rds/transport.c	2006-07-13 01:30:09 UTC (rev 132)
+++ trunk/linux/net/rds/transport.c	2006-07-14 21:37:50 UTC (rev 133)
@@ -47,6 +47,16 @@
 		(*trans)->listen_stop();
 }
 
+void rds_trans_print_stats(struct seq_file *seq)
+{
+	struct rds_transport **trans;
+
+	for (trans = transports; *trans; trans++) {
+		if ((*trans)->print_stats)
+			(*trans)->print_stats(seq);
+	}
+}
+
 /* XXX should be more clever, but this is easy for now */
 int __init rds_trans_init(void)
 {




More information about the rds-commits mailing list