From d002298e030e3afd159267a04e215aab45609e52 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Thu, 11 Sep 2003 04:16:57 -0700 Subject: [PATCH] [ATM]: seq_file for /proc/net/atm (devices) [1/8] (from romieu@fr.zoreil.com) seq_file conversion for proc/atm/devices: - code inspired from seq_file use in net/core/dev.c; - atm_dev_lock taken/released in atm_dev_seq_{start/stop}; - add a helper CREATE_SEQ_ENTRY() similar to CREATE_ENTRY() (both are removed once conversion is done). - atm_dev_seq_{start/stop/next} done in net/atm/resource.[ch] to ease future handling of atm_devs and locking structure (per Chas suggestion) --- net/atm/proc.c | 86 +++++++++++++++++++++++++++------------------ net/atm/resources.c | 29 +++++++++++++++ net/atm/resources.h | 5 +++ 3 files changed, 86 insertions(+), 34 deletions(-) diff --git a/net/atm/proc.c b/net/atm/proc.c index d493ab2cd4203..37a7b5de89f89 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -64,32 +65,30 @@ static struct file_operations proc_spec_atm_operations = { .read = proc_spec_atm_read, }; -static void add_stats(char *buf,const char *aal, +static void add_stats(struct seq_file *seq, const char *aal, const struct k_atm_aal_stats *stats) { - sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal, + seq_printf(seq, "%s ( %d %d %d %d %d )", aal, atomic_read(&stats->tx),atomic_read(&stats->tx_err), atomic_read(&stats->rx),atomic_read(&stats->rx_err), atomic_read(&stats->rx_drop)); } - -static void atm_dev_info(const struct atm_dev *dev,char *buf) +static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev) { - int off,i; + int i; - off = sprintf(buf,"%3d %-8s",dev->number,dev->type); + seq_printf(seq, "%3d %-8s", dev->number, dev->type); for (i = 0; i < ESI_LEN; i++) - off += sprintf(buf+off,"%02x",dev->esi[i]); - strcat(buf," "); - add_stats(buf,"0",&dev->stats.aal0); - strcat(buf," "); - add_stats(buf,"5",&dev->stats.aal5); - sprintf(strchr(buf,0), "\t[%d]", atomic_read(&dev->refcnt)); - strcat(buf,"\n"); + seq_printf(seq, "%02x", dev->esi[i]); + seq_puts(seq, " "); + add_stats(seq, "0", &dev->stats.aal0); + seq_puts(seq, " "); + add_stats(seq, "5", &dev->stats.aal5); + seq_printf(seq, "\t[%d]", atomic_read(&dev->refcnt)); + seq_putc(seq, '\n'); } - #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) @@ -303,29 +302,40 @@ lec_info(struct lec_arp_table *entry, char *buf) #endif -static int atm_devices_info(loff_t pos,char *buf) +static int atm_dev_seq_show(struct seq_file *seq, void *v) { - struct atm_dev *dev; - struct list_head *p; - int left; + static char atm_dev_banner[] = + "Itf Type ESI/\"MAC\"addr " + "AAL(TX,err,RX,err,drop) ... [refcnt]\n"; + + if (v == (void *)1) + seq_puts(seq, atm_dev_banner); + else { + struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list); - if (!pos) { - return sprintf(buf,"Itf Type ESI/\"MAC\"addr " - "AAL(TX,err,RX,err,drop) ... [refcnt]\n"); - } - left = pos-1; - spin_lock(&atm_dev_lock); - list_for_each(p, &atm_devs) { - dev = list_entry(p, struct atm_dev, dev_list); - if (left-- == 0) { - atm_dev_info(dev,buf); - spin_unlock(&atm_dev_lock); - return strlen(buf); - } + atm_dev_info(seq, dev); } - spin_unlock(&atm_dev_lock); - return 0; + return 0; } + +static struct seq_operations atm_dev_seq_ops = { + .start = atm_dev_seq_start, + .next = atm_dev_seq_next, + .stop = atm_dev_seq_stop, + .show = atm_dev_seq_show, +}; + +static int atm_dev_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &atm_dev_seq_ops); +} + +static struct file_operations devices_seq_fops = { + .open = atm_dev_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; /* * FIXME: it isn't safe to walk the VCC list without turning off interrupts. @@ -630,6 +640,14 @@ void atm_proc_dev_deregister(struct atm_dev *dev) kfree(dev->proc_name); } +#define CREATE_SEQ_ENTRY(name) \ + do { \ + name = create_proc_entry(#name, S_IRUGO, atm_proc_root); \ + if (!name) \ + goto cleanup; \ + name->proc_fops = & name##_seq_fops; \ + name->owner = THIS_MODULE; \ + } while (0) #define CREATE_ENTRY(name) \ name = create_proc_entry(#name,0,atm_proc_root); \ @@ -663,7 +681,7 @@ int __init atm_proc_init(void) atm_proc_root = proc_mkdir("net/atm",NULL); if (!atm_proc_root) return -ENOMEM; - CREATE_ENTRY(devices); + CREATE_SEQ_ENTRY(devices); CREATE_ENTRY(pvc); CREATE_ENTRY(svc); CREATE_ENTRY(vc); diff --git a/net/atm/resources.c b/net/atm/resources.c index 732dde666a555..bbae94bd7f207 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -395,6 +395,35 @@ done: return error; } +static __inline__ void *dev_get_idx(loff_t left) +{ + struct list_head *p; + + list_for_each(p, &atm_devs) { + if (!--left) + break; + } + return (p != &atm_devs) ? p : NULL; +} + +void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) +{ + spin_lock(&atm_dev_lock); + return *pos ? dev_get_idx(*pos) : (void *) 1; +} + +void atm_dev_seq_stop(struct seq_file *seq, void *v) +{ + spin_unlock(&atm_dev_lock); +} + +void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + v = (v == (void *)1) ? atm_devs.next : ((struct list_head *)v)->next; + return (v == &atm_devs) ? NULL : v; +} + EXPORT_SYMBOL(atm_dev_register); EXPORT_SYMBOL(atm_dev_deregister); diff --git a/net/atm/resources.h b/net/atm/resources.h index 1b6bad8db9ccb..5f69a949eebf4 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -21,6 +21,11 @@ int atm_dev_ioctl(unsigned int cmd, unsigned long arg); #include +void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos); +void atm_dev_seq_stop(struct seq_file *seq, void *v); +void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos); + + int atm_proc_dev_register(struct atm_dev *dev); void atm_proc_dev_deregister(struct atm_dev *dev); -- 2.53.0