From fbc1cf5cfa15c6ee7772bc8cd127f218155e3614 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <shemminger@osdl.org>
Date: Tue, 19 Aug 2003 07:27:25 -0700
Subject: [PATCH] [NET]: Convert 802/tr to seq_file.

---
 net/802/tr.c | 137 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 81 insertions(+), 56 deletions(-)

diff --git a/net/802/tr.c b/net/802/tr.c
index 6e029d3932fe..1eb39e9e2e57 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -33,6 +33,7 @@
 #include <linux/timer.h>
 #include <linux/net.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/init.h>
 #include <net/arp.h>
 
@@ -456,84 +457,108 @@ static void rif_check_expire(unsigned long dummy)
  *	routing.
  */
  
-#ifndef CONFIG_PROC_FS
-static int rif_get_info(char *buffer,char **start, off_t offset, int length)  { return 0;}
-#else
-static int rif_get_info(char *buffer,char **start, off_t offset, int length) 
+#ifdef CONFIG_PROC_FS
+/* Magic token to indicate first entry (header line) */
+#define RIF_PROC_START	((void *)1)
+
+static struct rif_cache_s *rif_get_idx(loff_t pos)
+{
+	int i;
+	struct rif_cache_s *entry;
+	loff_t off = 0;
+
+	for(i=0;i < RIF_TABLE_SIZE;i++) 
+		for(entry=rif_table[i];entry;entry=entry->next) {
+			if (off == pos)
+				return entry;
+			++off;
+		}
+
+	return NULL;
+}
+
+static void *rif_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	int len=0;
-	off_t begin=0;
-	off_t pos=0;
-	int size,i,j,rcf_len,segment,brdgnmb;
-	unsigned long now=jiffies;
 	unsigned long flags;
 
-	rif_cache entry;
+	spin_lock_irqsave(&rif_lock, flags);
+	seq->private = (void *) flags;
+
+	return *pos ? rif_get_idx(*pos - 1) : RIF_PROC_START;
+}
+
+static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	return rif_get_idx(*pos++);
+}
 
-	size=sprintf(buffer,
+static void rif_seq_stop(struct seq_file *seq, void *v)
+{
+	unsigned long flags = (unsigned long) seq->private;
+	spin_lock_irqsave(&rif_lock, flags);
+}
+
+static int rif_seq_show(struct seq_file *seq, void *v)
+{
+	int j, rcf_len, segment, brdgnmb;
+	rif_cache entry = v;
+
+	if (v == RIF_PROC_START)
+		seq_puts(seq,
 		     "if     TR address       TTL   rcf   routing segments\n");
-	pos+=size;
-	len+=size;
+	else {
+		struct net_device *dev = dev_get_by_index(entry->iface);
 
-	spin_lock_irqsave(&rif_lock,flags);
-	for(i=0;i < RIF_TABLE_SIZE;i++) 
-	{
-		for(entry=rif_table[i];entry;entry=entry->next) {
-			struct net_device *dev = __dev_get_by_index(entry->iface);
+		seq_printf(seq, "%s %02X:%02X:%02X:%02X:%02X:%02X %7li ",
+			   dev?dev->name:"?",
+			   entry->addr[0],entry->addr[1],entry->addr[2],
+			   entry->addr[3],entry->addr[4],entry->addr[5],
+			   sysctl_tr_rif_timeout-(jiffies-entry->last_used));
 
-			size=sprintf(buffer+len,"%s %02X:%02X:%02X:%02X:%02X:%02X %7li ",
-				     dev?dev->name:"?",entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
-				     sysctl_tr_rif_timeout-(now-entry->last_used));
-			len+=size;
-			pos=begin+len;
 			if (entry->local_ring)
-			        size=sprintf(buffer+len,"local\n");
+			        seq_puts(seq, "local\n");
 			else {
-			        size=sprintf(buffer+len,"%04X", ntohs(entry->rcf));
+
+				seq_printf(seq, "%04X", ntohs(entry->rcf));
 				rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; 
 				if (rcf_len)
 				        rcf_len >>= 1;
 				for(j = 1; j < rcf_len; j++) {
 					if(j==1) {
 						segment=ntohs(entry->rseg[j-1])>>4;
-						len+=size;
-						pos=begin+len;
-						size=sprintf(buffer+len,"  %03X",segment);
+						seq_printf(seq,"  %03X",segment);
 					};
 					segment=ntohs(entry->rseg[j])>>4;
 					brdgnmb=ntohs(entry->rseg[j-1])&0x00f;
-					len+=size;
-					pos=begin+len;
-					size=sprintf(buffer+len,"-%01X-%03X",brdgnmb,segment);
+					seq_printf(seq,"-%01X-%03X",brdgnmb,segment);
 				}
-				len+=size;
-				pos=begin+len;
-			        size=sprintf(buffer+len,"\n");
+				seq_putc(seq, '\n');
 			}
-			len+=size;
-			pos=begin+len;
-
-			if(pos<offset) 
-			{
-				len=0;
-				begin=pos;
-			}
-			if(pos>offset+length)
-				break;
 	   	}
-		if(pos>offset+length)
-			break;
-	}
-	spin_unlock_irqrestore(&rif_lock,flags);
+	return 0;
+}
+
+
+static struct seq_operations rif_seq_ops = {
+	.start = rif_seq_start,
+	.next  = rif_seq_next,
+	.stop  = rif_seq_stop,
+	.show  = rif_seq_show,
+};
 
-	*start=buffer+(offset-begin); /* Start of wanted data */
-	len-=(offset-begin);    /* Start slop */
-	if(len>length)
-		len=length;    /* Ending slop */
-	if (len<0)
-		len=0;
-	return len;
+static int rif_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &rif_seq_ops);
 }
+
+static struct file_operations rif_seq_fops = {
+	.owner	 = THIS_MODULE,
+	.open    = rif_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
 #endif
 
 /*
@@ -549,7 +574,7 @@ static int __init rif_init(void)
 	rif_timer.function = rif_check_expire;
 	add_timer(&rif_timer);
 
-	proc_net_create("tr_rif",0,rif_get_info);
+	proc_net_fops_create("tr_rif", S_IRUGO, &rif_seq_fops);
 	return 0;
 }
 
-- 
2.30.9