netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Convert ipvs to use seq_file.
@ 2003-09-15 21:39 Stephen Hemminger
  2003-09-15 22:56 ` Roberto Nibali
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Hemminger @ 2003-09-15 21:39 UTC (permalink / raw)
  To: David S. Miller; +Cc: lvs-users, netdev

Convert IPVS (for 2.6.0-test5) to use seq_file for the /proc interface.
Got rid of gratuitous 64 column trailing blank padding.

P.s: how come there is no MAINTAINER listed for IPVS?

diff -urNp -X dontdiff linux-2.5/net/ipv4/ipvs/ip_vs_app.c linux-2.5-net/net/ipv4/ipvs/ip_vs_app.c
--- linux-2.5/net/ipv4/ipvs/ip_vs_app.c	2003-09-15 09:57:15.000000000 -0700
+++ linux-2.5-net/net/ipv4/ipvs/ip_vs_app.c	2003-09-15 10:30:18.000000000 -0700
@@ -35,6 +35,7 @@
 #include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <net/ip_vs.h>
 
@@ -480,55 +481,104 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *
 }
 
 
+#ifdef CONFIG_PROC_FS
 /*
  *	/proc/net/ip_vs_app entry function
  */
-static int
-ip_vs_app_getinfo(char *buffer, char **start, off_t offset, int length)
+#define SEQ_START_TOKEN	((void *)1)
+
+static struct ip_vs_app *ip_vs_app_idx(loff_t pos)
 {
-	off_t pos=0;
-	int len=0;
-	char temp[64];
-	struct ip_vs_app *app, *inc;
+	loff_t off = 0;
 	struct list_head *e, *i;
 
-	pos = 64;
-	if (pos > offset) {
-		len += sprintf(buffer+len, "%-63s\n",
-			       "prot port    usecnt name");
+	list_for_each(e, &ip_vs_app_list) {
+		struct ip_vs_app *app
+			= list_entry(e, struct ip_vs_app, a_list);
+		list_for_each (i, &app->incs_list) {
+			if (off == pos)
+				return list_entry(i, struct ip_vs_app, a_list);
+			++off;
+		}	
 	}
+	return NULL;
+
+}
 
+static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos)
+{
 	down(&__ip_vs_app_mutex);
-	list_for_each (e, &ip_vs_app_list) {
+	
+	return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ip_vs_app *inc, *app;
+	struct list_head *i, *e;
+
+	++*pos;
+	if (v == SEQ_START_TOKEN)
+		return ip_vs_app_idx(0);
+	
+	inc = v;
+	app = inc->app;
+
+	if ((i = inc->a_list.next) != &app->incs_list)
+		return list_entry(i, struct ip_vs_app, a_list);
+
+	/* go on to next application */
+	for (e = app->a_list.next; e != &ip_vs_app_list; e = e->next) {
 		app = list_entry(e, struct ip_vs_app, a_list);
 		list_for_each (i, &app->incs_list) {
-			inc = list_entry(i, struct ip_vs_app, a_list);
-
-			pos += 64;
-			if (pos <= offset)
-				continue;
-			sprintf(temp, "%-3s  %-7u %-6d %-17s",
-				ip_vs_proto_name(inc->protocol),
-				ntohs(inc->port),
-				atomic_read(&inc->usecnt),
-				inc->name);
-			len += sprintf(buffer+len, "%-63s\n", temp);
-			if (pos >= offset+length)
-				goto done;
+			return list_entry(i, struct ip_vs_app, a_list);
 		}
 	}
-  done:
+	return NULL;
+}
+
+static void ip_vs_app_seq_stop(struct seq_file *seq, void *v)
+{
 	up(&__ip_vs_app_mutex);
+}
 
-	*start = buffer+len-(pos-offset);       /* Start of wanted data */
-	len = pos-offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0;
-	return len;
+static int ip_vs_app_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == SEQ_START_TOKEN)
+		seq_puts(seq, "prot port    usecnt name\n");
+	else {
+		const struct ip_vs_app *inc = v;
+
+		seq_printf(seq, "%-3s  %-7u %-6d %-17s\n",
+			   ip_vs_proto_name(inc->protocol),
+			   ntohs(inc->port),
+			   atomic_read(&inc->usecnt),
+			   inc->name);
+	}
+	return 0;
 }
 
+static struct seq_operations ip_vs_app_seq_ops = {
+	.start = ip_vs_app_seq_start,
+	.next  = ip_vs_app_seq_next,
+	.stop  = ip_vs_app_seq_stop,
+	.show  = ip_vs_app_seq_show,
+};
+
+static int ip_vs_app_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ip_vs_app_seq_ops);
+}
+
+static struct file_operations ip_vs_app_fops = {
+	.owner	 = THIS_MODULE,
+	.open    = ip_vs_app_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+#endif
+
 
 /*
  *	Replace a segment of data with a new segment
@@ -577,7 +627,7 @@ int ip_vs_skb_replace(struct sk_buff *sk
 int ip_vs_app_init(void)
 {
 	/* we will replace it with proc_net_ipvs_create() soon */
-	proc_net_create("ip_vs_app", 0, ip_vs_app_getinfo);
+	proc_net_fops_create("ip_vs_app", 0, &ip_vs_app_fops);
 	return 0;
 }
 
diff -urNp -X dontdiff linux-2.5/net/ipv4/ipvs/ip_vs_conn.c linux-2.5-net/net/ipv4/ipvs/ip_vs_conn.c
--- linux-2.5/net/ipv4/ipvs/ip_vs_conn.c	2003-09-15 09:57:15.000000000 -0700
+++ linux-2.5-net/net/ipv4/ipvs/ip_vs_conn.c	2003-09-15 10:27:45.000000000 -0700
@@ -30,6 +30,7 @@
 #include <linux/compiler.h>
 #include <linux/vmalloc.h>
 #include <linux/proc_fs.h>		/* for proc_net_* */
+#include <linux/seq_file.h>
 #include <linux/jhash.h>
 #include <linux/random.h>
 
@@ -188,14 +189,13 @@ static inline struct ip_vs_conn *__ip_vs
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
-	struct list_head *l,*e;
+	struct list_head *e;
 
 	hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
-	l = &ip_vs_conn_tab[hash];
 
 	ct_read_lock(hash);
 
-	for (e=l->next; e!=l; e=e->next) {
+	list_for_each(e, &ip_vs_conn_tab[hash]) {
 		cp = list_entry(e, struct ip_vs_conn, c_list);
 		if (s_addr==cp->caddr && s_port==cp->cport &&
 		    d_port==cp->vport && d_addr==cp->vaddr &&
@@ -242,17 +242,16 @@ struct ip_vs_conn *ip_vs_conn_out_get
 {
 	unsigned hash;
 	struct ip_vs_conn *cp, *ret=NULL;
-	struct list_head *l,*e;
+	struct list_head *e;
 
 	/*
 	 *	Check for "full" addressed entries
 	 */
 	hash = ip_vs_conn_hashkey(protocol, d_addr, d_port);
-	l = &ip_vs_conn_tab[hash];
 
 	ct_read_lock(hash);
 
-	for (e=l->next; e!=l; e=e->next) {
+	list_for_each(e, &ip_vs_conn_tab[hash]) {
 		cp = list_entry(e, struct ip_vs_conn, c_list);
 		if (d_addr == cp->caddr && d_port == cp->cport &&
 		    s_port == cp->dport && s_addr == cp->daddr &&
@@ -615,61 +614,116 @@ ip_vs_conn_new(int proto, __u32 caddr, _
 /*
  *	/proc/net/ip_vs_conn entries
  */
-static int
-ip_vs_conn_getinfo(char *buffer, char **start, off_t offset, int length)
-{
-	off_t pos=0;
-	int idx, len=0;
-	char temp[70];
-	struct ip_vs_conn *cp;
-	struct list_head *l, *e;
+#ifdef CONFIG_PROC_FS
 
-	pos = 128;
-	if (pos > offset) {
-		len += sprintf(buffer+len, "%-127s\n",
-			       "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Expires");
-	}
+#define SEQ_START_TOKEN	((void *)1)
 
+static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
+{
+	struct list_head *e;
+	int idx;
+	loff_t off = 0;
+	
 	for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) {
-		/*
-		 *	Lock is actually only need in next loop
-		 *	we are called from uspace: must stop bh.
-		 */
 		ct_read_lock_bh(idx);
+		list_for_each(e, &ip_vs_conn_tab[idx]) {
+			if (off == pos) {
+				seq->private = &ip_vs_conn_tab[idx];
+				return list_entry(e, struct ip_vs_conn, c_list);
+			}
+			++off;
+		}	
+		ct_read_unlock_bh(idx);
+	}
 
-		l = &ip_vs_conn_tab[idx];
-		for (e=l->next; e!=l; e=e->next) {
-			cp = list_entry(e, struct ip_vs_conn, c_list);
-			pos += 128;
-			if (pos <= offset)
-				continue;
-			sprintf(temp,
-				"%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu",
+	return NULL;
+}
+
+static void *ip_vs_conn_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	seq->private = NULL;
+	return *pos ? ip_vs_conn_array(seq, *pos - 1) :SEQ_START_TOKEN;
+}
+
+static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ip_vs_conn *cp = v;
+	struct list_head *e, *l = seq->private;
+	int idx;
+
+	++*pos;
+	if (v == SEQ_START_TOKEN) 
+		return ip_vs_conn_array(seq, 0);
+
+	/* more on same hash chain? */
+	if ((e = cp->c_list.next) != l)
+		return list_entry(e, struct ip_vs_conn, c_list);
+
+	idx = l - ip_vs_conn_tab;
+	ct_read_unlock_bh(idx);
+
+	while (++idx < IP_VS_CONN_TAB_SIZE) {
+		ct_read_lock_bh(idx);
+		list_for_each(e, &ip_vs_conn_tab[idx]) {
+			seq->private = &ip_vs_conn_tab[idx];
+			return list_entry(e, struct ip_vs_conn, c_list);
+		}	
+		ct_read_unlock_bh(idx);
+	}
+	seq->private = NULL;
+	return NULL;
+}
+
+static void ip_vs_conn_seq_stop(struct seq_file *seq, void *v)
+{
+	struct list_head *l = seq->private;
+
+	if (l) 
+		ct_read_unlock(l - ip_vs_conn_tab);
+}
+
+static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
+{
+
+	if (v == SEQ_START_TOKEN)
+		seq_puts(seq,
+   "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Expires\n");
+	else {
+		const struct ip_vs_conn *cp = v;
+
+		seq_printf(seq,
+			"%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu\n",
 				ip_vs_proto_name(cp->protocol),
 				ntohl(cp->caddr), ntohs(cp->cport),
 				ntohl(cp->vaddr), ntohs(cp->vport),
 				ntohl(cp->daddr), ntohs(cp->dport),
 				ip_vs_state_name(cp->protocol, cp->state),
 				(cp->timer.expires-jiffies)/HZ);
-			len += sprintf(buffer+len, "%-127s\n", temp);
-			if (pos >= offset+length) {
-				ct_read_unlock_bh(idx);
-				goto done;
-			}
-		}
-		ct_read_unlock_bh(idx);
 	}
-
-  done:
-	*start = buffer+len-(pos-offset);       /* Start of wanted data */
-	len = pos-offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0;
-	return len;
+	return 0;
 }
 
+static struct seq_operations ip_vs_conn_seq_ops = {
+	.start = ip_vs_conn_seq_start,
+	.next  = ip_vs_conn_seq_next,
+	.stop  = ip_vs_conn_seq_stop,
+	.show  = ip_vs_conn_seq_show,
+};
+
+static int ip_vs_conn_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ip_vs_conn_seq_ops);
+}
+
+static struct file_operations ip_vs_conn_fops = {
+	.owner	 = THIS_MODULE,
+	.open    = ip_vs_conn_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+#endif
+
 
 /*
  *      Randomly drop connection entries before running out of memory
@@ -707,7 +761,7 @@ void ip_vs_random_dropentry(void)
 {
 	int idx;
 	struct ip_vs_conn *cp;
-	struct list_head *l,*e;
+	struct list_head *e;
 	struct ip_vs_conn *ct;
 
 	/*
@@ -721,8 +775,7 @@ void ip_vs_random_dropentry(void)
 		 */
 		ct_write_lock(hash);
 
-		l = &ip_vs_conn_tab[hash];
-		for (e=l->next; e!=l; e=e->next) {
+		list_for_each(e, &ip_vs_conn_tab[hash]) {
 			cp = list_entry(e, struct ip_vs_conn, c_list);
 			if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT))
 				/* connection template */
@@ -775,7 +828,7 @@ static void ip_vs_conn_flush(void)
 {
 	int idx;
 	struct ip_vs_conn *cp;
-	struct list_head *l,*e;
+	struct list_head *e;
 	struct ip_vs_conn *ct;
 
   flush_again:
@@ -785,8 +838,7 @@ static void ip_vs_conn_flush(void)
 		 */
 		ct_write_lock_bh(idx);
 
-		l = &ip_vs_conn_tab[idx];
-		for (e=l->next; e!=l; e=e->next) {
+		list_for_each(e, &ip_vs_conn_tab[idx]) {
 			cp = list_entry(e, struct ip_vs_conn, c_list);
 			atomic_inc(&cp->refcnt);
 			ct_write_unlock(idx);
@@ -848,7 +900,7 @@ int ip_vs_conn_init(void)
 		__ip_vs_conntbl_lock_array[idx].l = RW_LOCK_UNLOCKED;
 	}
 
-	proc_net_create("ip_vs_conn", 0, ip_vs_conn_getinfo);
+	proc_net_fops_create("ip_vs_conn", 0, &ip_vs_conn_fops);
 
 	/* calculate the random value for connection hash */
 	get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
diff -urNp -X dontdiff linux-2.5/net/ipv4/ipvs/ip_vs_ctl.c linux-2.5-net/net/ipv4/ipvs/ip_vs_ctl.c
--- linux-2.5/net/ipv4/ipvs/ip_vs_ctl.c	2003-09-15 09:57:15.000000000 -0700
+++ linux-2.5-net/net/ipv4/ipvs/ip_vs_ctl.c	2003-09-15 12:52:15.000000000 -0700
@@ -31,6 +31,8 @@
 #include <linux/proc_fs.h>
 #include <linux/timer.h>
 #include <linux/swap.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
@@ -1507,207 +1509,253 @@ static struct ip_vs_sysctl_table ipv4_vs
 	 {0}}
 };
 
+#ifdef CONFIG_PROC_FS
+
+struct ip_vs_iter {
+	struct list_head *table;
+	int bucket;
+};
 
+
+#define SEQ_START_TOKEN	((void *)1)
 /*
  *	Write the contents of the VS rule table to a PROCfs file.
  *	(It is kept just for backward compatibility)
  */
-static inline char *ip_vs_fwd_name(unsigned flags)
+static inline const char *ip_vs_fwd_name(unsigned flags)
 {
-	char *fwd;
-
 	switch (flags & IP_VS_CONN_F_FWD_MASK) {
 	case IP_VS_CONN_F_LOCALNODE:
-		fwd = "Local";
-		break;
+		return "Local";
 	case IP_VS_CONN_F_TUNNEL:
-		fwd = "Tunnel";
-		break;
+		return "Tunnel";
 	case IP_VS_CONN_F_DROUTE:
-		fwd = "Route";
-		break;
+		return "Route";
 	default:
-		fwd = "Masq";
+		return "Masq";
 	}
-	return fwd;
 }
 
-static inline int sprintf_dest(char *str, struct ip_vs_dest *dest)
-{
-	return sprintf(str, "  -> %08X:%04X      %-7s %-6d %-10d %-10d",
-		       ntohl(dest->addr), ntohs(dest->port),
-		       ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
-		       atomic_read(&dest->weight),
-		       atomic_read(&dest->activeconns),
-		       atomic_read(&dest->inactconns));
-}
 
-static int ip_vs_get_info(char *buf, char **start, off_t offset, int length)
+/* Get the Nth entry in the two lists */
+static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
 {
-	int len=0;
-	off_t pos=0;
-	char temp[64], temp2[32];
+	struct ip_vs_iter *iter = seq->private;
 	int idx;
-	struct ip_vs_service *svc;
-	struct ip_vs_dest *dest;
-	struct list_head *l, *e, *p, *q;
-
-	/*
-	 * Note: since the length of the buffer is usually the multiple
-	 * of 512, it is good to use fixed record of the divisor of 512,
-	 * so that records won't be truncated at buffer boundary.
-	 */
-	pos = 192;
-	if (pos > offset) {
-		sprintf(temp,
-			"IP Virtual Server version %d.%d.%d (size=%d)",
-			NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE);
-		len += sprintf(buf+len, "%-63s\n", temp);
-		len += sprintf(buf+len, "%-63s\n",
-			       "Prot LocalAddress:Port Scheduler Flags");
-		len += sprintf(buf+len, "%-63s\n",
-			       "  -> RemoteAddress:Port Forward Weight ActiveConn InActConn");
-	}
+	struct list_head *e;
 
-	read_lock_bh(&__ip_vs_svc_lock);
-
-	/* print the service table hashed by <protocol,addr,port> */
+	/* look in hash by protocol */
 	for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
-		l = &ip_vs_svc_table[idx];
-		for (e=l->next; e!=l; e=e->next) {
-			svc = list_entry(e, struct ip_vs_service, s_list);
-			pos += 64;
-			if (pos > offset) {
-				if (svc->flags & IP_VS_SVC_F_PERSISTENT)
-					sprintf(temp2, "persistent %d %08X",
-						svc->timeout,
-						ntohl(svc->netmask));
-				else
-					temp2[0] = '\0';
-
-				sprintf(temp, "%s  %08X:%04X %s %s",
-					ip_vs_proto_name(svc->protocol),
-					ntohl(svc->addr),
-					ntohs(svc->port),
-					svc->scheduler->name, temp2);
-				len += sprintf(buf+len, "%-63s\n", temp);
-				if (len >= length)
-					goto done;
-			}
-
-			p = &svc->destinations;
-			for (q=p->next; q!=p; q=q->next) {
-				dest = list_entry(q, struct ip_vs_dest, n_list);
-				pos += 64;
-				if (pos <= offset)
-					continue;
-				sprintf_dest(temp, dest);
-				len += sprintf(buf+len, "%-63s\n", temp);
-				if (len >= length)
-					goto done;
+		list_for_each(e, &ip_vs_svc_table[idx]) {
+			if (pos-- == 0){
+				iter->table = ip_vs_svc_table;
+				iter->bucket = idx;
+				return list_entry(e, struct ip_vs_service, s_list);
 			}
 		}
 	}
 
-	/* print the service table hashed by fwmark */
+	/* keep looking in fwmark */
 	for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
-		l = &ip_vs_svc_fwm_table[idx];
-		for (e=l->next; e!=l; e=e->next) {
-			svc = list_entry(e, struct ip_vs_service, f_list);
-			pos += 64;
-			if (pos > offset) {
-				if (svc->flags & IP_VS_SVC_F_PERSISTENT)
-					sprintf(temp2, "persistent %d %08X",
-						svc->timeout,
-						ntohl(svc->netmask));
-				else
-					temp2[0] = '\0';
-
-				sprintf(temp, "FWM  %08X %s %s",
-					svc->fwmark,
-					svc->scheduler->name, temp2);
-				len += sprintf(buf+len, "%-63s\n", temp);
-				if (len >= length)
-					goto done;
+		list_for_each(e, &ip_vs_svc_fwm_table[idx]) {
+			if (pos-- == 0) {
+				iter->table = ip_vs_svc_fwm_table;
+				iter->bucket = idx;
+				return list_entry(e, struct ip_vs_service, f_list);
 			}
+		}
+	}
+
+	return NULL;
+}
 
-			p = &svc->destinations;
-			for (q=p->next; q!=p; q=q->next) {
-				dest = list_entry(q, struct ip_vs_dest, n_list);
-				pos += 64;
-				if (pos <= offset)
-					continue;
-				sprintf_dest(temp, dest);
-				len += sprintf(buf+len, "%-63s\n", temp);
-				if (len >= length)
-					goto done;
+static void *ip_vs_info_seq_start(struct seq_file *seq, loff_t *pos)
+{
+
+	read_lock_bh(&__ip_vs_svc_lock);
+	return *pos ? ip_vs_info_array(seq, *pos - 1) : SEQ_START_TOKEN;
+}
+
+
+static void *ip_vs_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct list_head *e;
+	struct ip_vs_iter *iter;
+	struct ip_vs_service *svc;
+
+	++*pos;
+	if (v == SEQ_START_TOKEN)
+		return ip_vs_info_array(seq,0);
+	
+	svc = v;
+	iter = seq->private;
+	
+	if (iter->table == ip_vs_svc_table) {
+		/* next service in table hashed by protocol */
+		if ((e = svc->s_list.next) != &ip_vs_svc_table[iter->bucket])
+			return list_entry(e, struct ip_vs_service, s_list);
+
+
+		while (++iter->bucket < IP_VS_SVC_TAB_SIZE) {
+			list_for_each(e, &ip_vs_svc_table[iter->bucket]) {
+				return list_entry(e, struct ip_vs_service, s_list);
 			}
 		}
+
+		iter->table = ip_vs_svc_fwm_table;
+		iter->bucket = -1;
+		goto scan_fwmark;
 	}
 
-  done:
+	/* next service in hashed by fwmark */
+	if ((e = svc->f_list.next) != &ip_vs_svc_fwm_table[iter->bucket])
+		return list_entry(e, struct ip_vs_service, f_list);
+
+ scan_fwmark:
+	while (++iter->bucket < IP_VS_SVC_TAB_SIZE) {
+		list_for_each(e, &ip_vs_svc_fwm_table[iter->bucket]) 
+			return list_entry(e, struct ip_vs_service, f_list);
+	}
+
+	return NULL;
+}
+
+static void ip_vs_info_seq_stop(struct seq_file *seq, void *v)
+{
 	read_unlock_bh(&__ip_vs_svc_lock);
+}
+
+
+static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq,
+			"IP Virtual Server version %d.%d.%d (size=%d)\n",
+			NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE);
+		seq_puts(seq,
+			 "Prot LocalAddress:Port Scheduler Flags\n");
+		seq_puts(seq,
+			 "  -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n");
+	} else {
+		const struct ip_vs_service *svc = v;
+		const struct ip_vs_iter *iter = seq->private;
+		const struct ip_vs_dest *dest;
+
+		if (iter->table == ip_vs_svc_table) 
+			seq_printf(seq, "%s  %08X:%04X %s ",
+				   ip_vs_proto_name(svc->protocol),
+				   ntohl(svc->addr),
+				   ntohs(svc->port),
+				   svc->scheduler->name);
+		else
+			seq_printf(seq, "FWM  %08X %s ",
+				   svc->fwmark, svc->scheduler->name);
+
+		if (svc->flags & IP_VS_SVC_F_PERSISTENT)
+			seq_printf(seq, "persistent %d %08X\n",
+				svc->timeout,
+				ntohl(svc->netmask));
+		else
+			seq_putc(seq, '\n');
 
-	*start = buf+len-(pos-offset);          /* Start of wanted data */
-	len = pos-offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0;
-	return len;
+		list_for_each_entry(dest, &svc->destinations, n_list) {
+			seq_printf(seq, 
+				   "  -> %08X:%04X      %-7s %-6d %-10d %-10d\n",
+				   ntohl(dest->addr), ntohs(dest->port),
+				   ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
+				   atomic_read(&dest->weight),
+				   atomic_read(&dest->activeconns),
+				   atomic_read(&dest->inactconns));
+		}
+	}
+	return 0;
 }
 
+static struct seq_operations ip_vs_info_seq_ops = {
+	.start = ip_vs_info_seq_start,
+	.next  = ip_vs_info_seq_next,
+	.stop  = ip_vs_info_seq_stop,
+	.show  = ip_vs_info_seq_show,
+};
+
+static int ip_vs_info_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct ip_vs_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &ip_vs_info_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq	     = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+static struct file_operations ip_vs_info_fops = {
+	.owner	 = THIS_MODULE,
+	.open    = ip_vs_info_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release_private,
+};
+
+#endif
 
 struct ip_vs_stats ip_vs_stats;
 
-static int
-ip_vs_stats_get_info(char *buf, char **start, off_t offset, int length)
+#ifdef CONFIG_PROC_FS
+static int ip_vs_stats_show(struct seq_file *seq, void *v)
 {
-	int len=0;
-	off_t pos=0;
-	char temp[64];
-
-	pos += 320;
-	if (pos > offset) {
-		len += sprintf(buf+len, "%-63s\n%-63s\n",
-/*                              01234567 01234567 01234567 0123456701234567 0123456701234567 */
-			       "   Total Incoming Outgoing         Incoming         Outgoing",
-			       "   Conns  Packets  Packets            Bytes            Bytes");
-
-		spin_lock_bh(&ip_vs_stats.lock);
-		sprintf(temp, "%8X %8X %8X %8X%08X %8X%08X",
-			ip_vs_stats.conns,
-			ip_vs_stats.inpkts,
-			ip_vs_stats.outpkts,
-			(__u32)(ip_vs_stats.inbytes>>32),
-			(__u32)ip_vs_stats.inbytes,
-			(__u32)(ip_vs_stats.outbytes>>32),
-			(__u32)ip_vs_stats.outbytes);
-		len += sprintf(buf+len, "%-62s\n\n", temp);
-
-		len += sprintf(buf+len, "%-63s\n",
-/*                              01234567 01234567 01234567 0123456701234567 0123456701234567 */
-			       " Conns/s   Pkts/s   Pkts/s          Bytes/s          Bytes/s");
-		sprintf(temp, "%8X %8X %8X %16X %16X",
+
+/*               01234567 01234567 01234567 0123456701234567 0123456701234567 */
+	seq_puts(seq,
+		 "   Total Incoming Outgoing         Incoming         Outgoing\n");
+	seq_printf(seq, 	   
+		   "   Conns  Packets  Packets            Bytes            Bytes\n");
+
+	spin_lock_bh(&ip_vs_stats.lock);
+	seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", ip_vs_stats.conns,
+		   ip_vs_stats.inpkts, ip_vs_stats.outpkts,
+		   ip_vs_stats.inbytes, ip_vs_stats.outbytes);
+
+/*                 01234567 01234567 01234567 0123456701234567 0123456701234567 */
+	seq_puts(seq,
+		   " Conns/s   Pkts/s   Pkts/s          Bytes/s          Bytes/s\n");
+	seq_printf(seq,"%8X %8X %8X %16X %16X\n",
 			ip_vs_stats.cps,
 			ip_vs_stats.inpps,
 			ip_vs_stats.outpps,
 			ip_vs_stats.inbps,
 			ip_vs_stats.outbps);
-		len += sprintf(buf+len, "%-63s\n", temp);
+	spin_unlock_bh(&ip_vs_stats.lock);
 
-		spin_unlock_bh(&ip_vs_stats.lock);
-	}
+	return 0;
+}
 
-	*start = buf+len-(pos-offset);          /* Start of wanted data */
-	len = pos-offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0;
-	return len;
+static int ip_vs_stats_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ip_vs_stats_show, NULL);
 }
 
+static struct file_operations ip_vs_stats_fops = {
+	.owner = THIS_MODULE,
+	.open = ip_vs_stats_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+#endif
 
 /*
  *	Set timeout values for tcp tcpfin udp in the timeout_table.
@@ -2195,8 +2243,8 @@ int ip_vs_control_init(void)
 		return ret;
 	}
 
-	proc_net_create("ip_vs", 0, ip_vs_get_info);
-	proc_net_create("ip_vs_stats", 0, ip_vs_stats_get_info);
+	proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
+	proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
 
 	ipv4_vs_table.sysctl_header =
 		register_sysctl_table(ipv4_vs_table.root_dir, 0);

^ permalink raw reply	[flat|nested] 5+ messages in thread
* RE: [PATCH] Convert ipvs to use seq_file.
@ 2003-09-15 21:56 Peter Mueller
  2003-09-15 22:01 ` David S. Miller
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Mueller @ 2003-09-15 21:56 UTC (permalink / raw)
  To: 'LinuxVirtualServer.org users mailing list.',
	David S. Miller, 'Stephen Hemminger'
  Cc: netdev

Hello Stephen,

> P.s: how come there is no MAINTAINER listed for IPVS?

Wensong Zhang is the maintainer; where did you expect to see a maintainer
listed at?  The LVS-developers that seem to be most active are:

Wensong Zhang
Julian Atanasaov
Simon Horman ('Horms')
Alexandre Cassen
Roberto Nibali ('Ratz')
Joseph Mack

AFAIK Redhat takes the LVS-source and patches it up at their end for
Pirahna, so patches should probably not go to RH.

Hope it helps,

Peter

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

end of thread, other threads:[~2003-09-15 22:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-15 21:39 [PATCH] Convert ipvs to use seq_file Stephen Hemminger
2003-09-15 22:56 ` Roberto Nibali
2003-09-15 22:49   ` David S. Miller
  -- strict thread matches above, loose matches on Subject: below --
2003-09-15 21:56 Peter Mueller
2003-09-15 22:01 ` David S. Miller

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