Commit c330a7d8 authored by Chas Williams's avatar Chas Williams Committed by Hideaki Yoshifuji

[ATM]: seq_file for /proc/net/atm (arp) [6/8] (from romieu@fr.zoreil.com)

seq_file support for /proc/net/atm/arp:
- svc_addr/atmarp_info(): seq_printf/seq_putc replace sprintf and friends;
- arp_getidx/arp_vcc_walk() take care of the usual seq_file cursor
  positionning: they both return NULL until the cursor has reached its
  position. struct atm_arp_state is updated accordingly;
- arp_seq_{stop/start} are responsible for clip_tbl_hook (un)locking;
- module refcounting is done in arp_seq_open()/arp_seq_release();
- atm_lec_info() is removed.

Chas's suggestions applied since last version:
- atm_arp_xxx renamed to arp_xxx;
- atm_seq_arp_fops renamed to arp_seq_fops.

Chas didn't ask for it but I renamed arp_vc_walk to arp_vcc_walk.
parent 535e2c6a
...@@ -91,75 +91,67 @@ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev) ...@@ -91,75 +91,67 @@ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
{ {
static int code[] = { 1,2,10,6,1,0 }; static int code[] = { 1,2,10,6,1,0 };
static int e164[] = { 1,8,4,6,1,0 }; static int e164[] = { 1,8,4,6,1,0 };
int *fields;
int len,i,j,pos;
len = 0;
if (*addr->sas_addr.pub) { if (*addr->sas_addr.pub) {
strcpy(buf,addr->sas_addr.pub); seq_printf(seq, "%s", addr->sas_addr.pub);
len = strlen(addr->sas_addr.pub); if (*addr->sas_addr.prv)
buf += len; seq_putc(seq, '+');
if (*addr->sas_addr.prv) { } else if (!*addr->sas_addr.prv) {
*buf++ = '+'; seq_printf(seq, "%s", "(none)");
len++; return;
}
} }
else if (!*addr->sas_addr.prv) {
strcpy(buf,"(none)");
return strlen(buf);
}
if (*addr->sas_addr.prv) { if (*addr->sas_addr.prv) {
len += 44; unsigned char *prv = addr->sas_addr.prv;
pos = 0; int *fields;
fields = *addr->sas_addr.prv == ATM_AFI_E164 ? e164 : code; int i, j;
fields = *prv == ATM_AFI_E164 ? e164 : code;
for (i = 0; fields[i]; i++) { for (i = 0; fields[i]; i++) {
for (j = fields[i]; j; j--) { for (j = fields[i]; j; j--)
sprintf(buf,"%02X",addr->sas_addr.prv[pos++]); seq_printf(seq, "%02X", *prv++);
buf += 2; if (fields[i+1])
} seq_putc(seq, '.');
if (fields[i+1]) *buf++ = '.';
} }
} }
return len;
} }
static void atmarp_info(struct seq_file *seq, struct net_device *dev,
static void atmarp_info(struct net_device *dev,struct atmarp_entry *entry, struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
struct clip_vcc *clip_vcc,char *buf)
{ {
unsigned char *ip; char buf[17];
int svc,off,ip_len; int svc, off;
svc = !clip_vcc || clip_vcc->vcc->sk->sk_family == AF_ATMSVC; svc = !clip_vcc || clip_vcc->vcc->sk->sk_family == AF_ATMSVC;
off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC", seq_printf(seq, "%-6s%-4s%-4s%5ld ", dev->name, svc ? "SVC" : "PVC",
!clip_vcc || clip_vcc->encap ? "LLC" : "NULL", !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
(jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/ (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/HZ);
HZ);
ip = (unsigned char *) &entry->ip; off = snprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip));
ip_len = sprintf(buf+off,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); while (off < 16)
off += ip_len; buf[off++] = ' ';
while (ip_len++ < 16) buf[off++] = ' '; buf[off] = '\0';
if (!clip_vcc) seq_printf(seq, "%s", buf);
if (!clip_vcc) {
if (time_before(jiffies, entry->expires)) if (time_before(jiffies, entry->expires))
strcpy(buf+off,"(resolving)\n"); seq_printf(seq, "(resolving)\n");
else sprintf(buf+off,"(expired, ref %d)\n", else
atomic_read(&entry->neigh->refcnt)); seq_printf(seq, "(expired, ref %d)\n",
else if (!svc) atomic_read(&entry->neigh->refcnt));
sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number, } else if (!svc) {
clip_vcc->vcc->vpi,clip_vcc->vcc->vci); seq_printf(seq, "%d.%d.%d\n", clip_vcc->vcc->dev->number,
else { clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
off += svc_addr(buf+off,&clip_vcc->vcc->remote); } else {
strcpy(buf+off,"\n"); svc_addr(seq, &clip_vcc->vcc->remote);
} seq_putc(seq, '\n');
}
} }
#endif /* CONFIG_ATM_CLIP */
#endif
struct vcc_state { struct vcc_state {
struct sock *sk; struct sock *sk;
...@@ -532,45 +524,154 @@ static struct file_operations svc_seq_fops = { ...@@ -532,45 +524,154 @@ static struct file_operations svc_seq_fops = {
}; };
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
static int atm_arp_info(loff_t pos,char *buf)
struct arp_state {
int bucket;
struct neighbour *n;
struct clip_vcc *vcc;
};
static void *arp_vcc_walk(struct arp_state *state,
struct atmarp_entry *e, loff_t *l)
{
struct clip_vcc *vcc = state->vcc;
if (!vcc)
vcc = e->vccs;
if (vcc == (void *)1) {
vcc = e->vccs;
--*l;
}
for (; vcc; vcc = vcc->next) {
if (--*l < 0)
break;
}
state->vcc = vcc;
return (*l < 0) ? state : NULL;
}
static void *arp_get_idx(struct arp_state *state, loff_t l)
{ {
struct neighbour *n; void *v = NULL;
int i,count;
if (!pos) { for (; state->bucket <= NEIGH_HASHMASK; state->bucket++) {
return sprintf(buf,"IPitf TypeEncp Idle IP address " for (; state->n; state->n = state->n->next) {
"ATM address\n"); v = arp_vcc_walk(state, NEIGH2ENTRY(state->n), &l);
if (v)
goto done;
}
state->n = clip_tbl_hook->hash_buckets[state->bucket + 1];
} }
if (!try_atm_clip_ops()) done:
return 0; return v;
count = pos; }
static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
{
struct arp_state *state = seq->private;
void *ret = (void *)1;
if (!clip_tbl_hook) {
state->bucket = -1;
goto out;
}
read_lock_bh(&clip_tbl_hook->lock); read_lock_bh(&clip_tbl_hook->lock);
for (i = 0; i <= NEIGH_HASHMASK; i++) state->bucket = 0;
for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) { state->n = clip_tbl_hook->hash_buckets[0];
struct atmarp_entry *entry = NEIGH2ENTRY(n); state->vcc = (void *)1;
struct clip_vcc *vcc; if (*pos)
ret = arp_get_idx(state, *pos);
if (!entry->vccs) { out:
if (--count) continue; return ret;
atmarp_info(n->dev,entry,NULL,buf); }
read_unlock_bh(&clip_tbl_hook->lock);
module_put(atm_clip_ops->owner); static void arp_seq_stop(struct seq_file *seq, void *v)
return strlen(buf); {
} struct arp_state *state = seq->private;
for (vcc = entry->vccs; vcc;
vcc = vcc->next) { if (state->bucket != -1)
if (--count) continue; read_unlock_bh(&clip_tbl_hook->lock);
atmarp_info(n->dev,entry,vcc,buf); }
read_unlock_bh(&clip_tbl_hook->lock);
module_put(atm_clip_ops->owner); static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
return strlen(buf); {
} struct arp_state *state = seq->private;
}
read_unlock_bh(&clip_tbl_hook->lock); v = arp_get_idx(state, 1);
*pos += !!PTR_ERR(v);
return v;
}
static int arp_seq_show(struct seq_file *seq, void *v)
{
static char atm_arp_banner[] =
"IPitf TypeEncp Idle IP address ATM address\n";
if (v == (void *)1)
seq_puts(seq, atm_arp_banner);
else {
struct arp_state *state = seq->private;
struct neighbour *n = state->n;
struct clip_vcc *vcc = state->vcc;
atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
}
return 0;
}
static struct seq_operations arp_seq_ops = {
.start = arp_seq_start,
.next = arp_seq_next,
.stop = arp_seq_stop,
.show = arp_seq_show,
};
static int arp_seq_open(struct inode *inode, struct file *file)
{
struct arp_state *state;
struct seq_file *seq;
int rc = -EAGAIN;
if (!try_atm_clip_ops())
goto out;
state = kmalloc(sizeof(*state), GFP_KERNEL);
if (!state) {
rc = -ENOMEM;
goto out_put;
}
rc = seq_open(file, &arp_seq_ops);
if (rc)
goto out_kfree;
seq = file->private_data;
seq->private = state;
out:
return rc;
out_put:
module_put(atm_clip_ops->owner); module_put(atm_clip_ops->owner);
return 0; out_kfree:
kfree(state);
goto out;
} }
#endif
static int arp_seq_release(struct inode *inode, struct file *file)
{
module_put(atm_clip_ops->owner);
return seq_release_private(inode, file);
}
static struct file_operations arp_seq_fops = {
.open = arp_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = arp_seq_release,
};
#endif /* CONFIG_ATM_CLIP */
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
static int atm_lec_info(loff_t pos,char *buf) static int atm_lec_info(loff_t pos,char *buf)
...@@ -786,7 +887,7 @@ int __init atm_proc_init(void) ...@@ -786,7 +887,7 @@ int __init atm_proc_init(void)
CREATE_SEQ_ENTRY(svc); CREATE_SEQ_ENTRY(svc);
CREATE_SEQ_ENTRY(vcc); CREATE_SEQ_ENTRY(vcc);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
CREATE_ENTRY(arp); CREATE_SEQ_ENTRY(arp);
#endif #endif
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
CREATE_ENTRY(lec); CREATE_ENTRY(lec);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment