summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@conectiva.com.br>2002-10-08 20:03:34 -0300
committerArnaldo Carvalho de Melo <acme@conectiva.com.br>2002-10-08 20:03:34 -0300
commit2bbb6a8e877ec67ce5c2ae3738252c476a4ff944 (patch)
treee229034c86fd52228d16f3314bbc25eaac26066c
parent797ef46be7164f00e4e76a06cfd4a4e99393b76a (diff)
o pppoe: use seq_file for proc stuff
Also make it conditional on CONFIG_PROC_FS
-rw-r--r--drivers/net/pppoe.c158
1 files changed, 107 insertions, 51 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 2df76282b619..b82d4d46ec18 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -5,7 +5,7 @@
* PPPoE --- PPP over Ethernet (RFC 2516)
*
*
- * Version: 0.6.10
+ * Version: 0.6.11
*
* 220102 : Fix module use count on failure in pppoe_create, pppox_sk -acme
* 030700 : Fixed connect logic to allow for disconnect.
@@ -35,6 +35,7 @@
* 121301 : New ppp channels interface; cannot unregister a channel
* from interrupts. Thus, we mark the socket as a ZOMBIE
* and do the unregistration later.
+ * 081002 : seq_file support for proc stuff -acme
*
* Author: Michal Ostrowski <mostrows@speakeasy.net>
* Contributors:
@@ -75,6 +76,7 @@
#include <linux/notifier.h>
#include <linux/file.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
@@ -974,63 +976,102 @@ end:
return error;
}
-int pppoe_proc_info(char *buffer, char **start, off_t offset, int length)
+#ifdef CONFIG_PROC_FS
+static int pppoe_seq_show(struct seq_file *seq, void *v)
{
struct pppox_opt *po;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- int size;
- int i;
+ char *dev_name;
- len += sprintf(buffer,
- "Id Address Device\n");
- pos = len;
+ if (v == (void *)1) {
+ seq_puts(seq, "Id Address Device\n");
+ goto out;
+ }
- write_lock_bh(&pppoe_hash_lock);
+ po = v;
+ dev_name = po->pppoe_pa.dev;
- for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+ seq_printf(seq, "%08X %02X:%02X:%02X:%02X:%02X:%02X %8s\n",
+ po->pppoe_pa.sid,
+ po->pppoe_pa.remote[0], po->pppoe_pa.remote[1],
+ po->pppoe_pa.remote[2], po->pppoe_pa.remote[3],
+ po->pppoe_pa.remote[4], po->pppoe_pa.remote[5], dev_name);
+out:
+ return 0;
+}
+
+static __inline__ struct pppox_opt *pppoe_get_idx(loff_t pos)
+{
+ struct pppox_opt *po = NULL;
+ int i = 0;
+
+ for (; i < PPPOE_HASH_SIZE; i++) {
po = item_hash_table[i];
while (po) {
- char *dev = po->pppoe_pa.dev;
-
- size = sprintf(buffer + len,
- "%08X %02X:%02X:%02X:%02X:%02X:%02X %8s\n",
- po->pppoe_pa.sid,
- po->pppoe_pa.remote[0],
- po->pppoe_pa.remote[1],
- po->pppoe_pa.remote[2],
- po->pppoe_pa.remote[3],
- po->pppoe_pa.remote[4],
- po->pppoe_pa.remote[5],
- dev);
- len += size;
- pos += size;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
+ if (!pos--)
+ goto out;
+ po = po->next;
+ }
+ }
+out:
+ return po;
+}
- if (pos > offset + length)
- break;
+static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ loff_t l = *pos;
- po = po->next;
+ read_lock_bh(&pppoe_hash_lock);
+ return l ? pppoe_get_idx(--l) : (void *)1;
+}
+
+static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct pppox_opt *po;
+
+ ++*pos;
+ if (v == (void *)1) {
+ po = pppoe_get_idx(0);
+ goto out;
+ }
+ po = v;
+ po = po->next;
+ if (!po) {
+ int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+
+ while (++hash < PPPOE_HASH_SIZE) {
+ po = item_hash_table[hash];
+ if (po)
+ break;
}
+ }
+out:
+ return po;
+}
- if (po)
- break;
- }
- write_unlock_bh(&pppoe_hash_lock);
+static void pppoe_seq_stop(struct seq_file *seq, void *v)
+{
+ read_unlock_bh(&pppoe_hash_lock);
+}
+
+struct seq_operations pppoe_seq_ops = {
+ .start = pppoe_seq_start,
+ .next = pppoe_seq_next,
+ .stop = pppoe_seq_stop,
+ .show = pppoe_seq_show,
+};
- *start = buffer + (offset - begin);
- len -= (offset - begin);
- if (len > length)
- len = length;
- if (len < 0)
- len = 0;
- return len;
+static int pppoe_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &pppoe_seq_ops);
}
+static struct file_operations pppoe_seq_fops = {
+ .open = pppoe_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#endif /* CONFIG_PROC_FS */
struct proto_ops pppoe_ops = {
.family = AF_PPPOX,
@@ -1061,13 +1102,28 @@ int __init pppoe_init(void)
{
int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
- if (err == 0) {
- dev_add_pack(&pppoes_ptype);
- dev_add_pack(&pppoed_ptype);
- register_netdevice_notifier(&pppoe_notifier);
- proc_net_create("pppoe", 0, pppoe_proc_info);
- }
+ if (err)
+ goto out;
+#ifdef CONFIG_PROC_FS
+{
+ struct proc_dir_entry *p = create_proc_entry("pppoe", S_IRUGO,
+ proc_net);
+ err = -ENOMEM;
+ if (!p)
+ goto out_unregister;
+
+ p->proc_fops = &pppoe_seq_fops;
+ err = 0;
+}
+#endif /* CONFIG_PROC_FS */
+ dev_add_pack(&pppoes_ptype);
+ dev_add_pack(&pppoed_ptype);
+ register_netdevice_notifier(&pppoe_notifier);
+out:
return err;
+out_unregister:
+ unregister_pppox_proto(PX_PROTO_OE);
+ goto out;
}
void __exit pppoe_exit(void)
@@ -1076,7 +1132,7 @@ void __exit pppoe_exit(void)
dev_remove_pack(&pppoes_ptype);
dev_remove_pack(&pppoed_ptype);
unregister_netdevice_notifier(&pppoe_notifier);
- proc_net_remove("pppoe");
+ remove_proc_entry("pppoe", proc_net);
}
module_init(pppoe_init);