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
seq_printf(seq, "(expired, ref %d)\n",
atomic_read(&entry->neigh->refcnt)); atomic_read(&entry->neigh->refcnt));
else if (!svc) } else if (!svc) {
sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number, seq_printf(seq, "%d.%d.%d\n", clip_vcc->vcc->dev->number,
clip_vcc->vcc->vpi,clip_vcc->vcc->vci); clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
else { } else {
off += svc_addr(buf+off,&clip_vcc->vcc->remote); svc_addr(seq, &clip_vcc->vcc->remote);
strcpy(buf+off,"\n"); 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 neighbour *n;
int i,count; struct clip_vcc *vcc;
};
if (!pos) { static void *arp_vcc_walk(struct arp_state *state,
return sprintf(buf,"IPitf TypeEncp Idle IP address " struct atmarp_entry *e, loff_t *l)
"ATM address\n"); {
struct clip_vcc *vcc = state->vcc;
if (!vcc)
vcc = e->vccs;
if (vcc == (void *)1) {
vcc = e->vccs;
--*l;
} }
if (!try_atm_clip_ops()) for (; vcc; vcc = vcc->next) {
return 0; if (--*l < 0)
count = pos; break;
read_lock_bh(&clip_tbl_hook->lock); }
for (i = 0; i <= NEIGH_HASHMASK; i++) state->vcc = vcc;
for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) { return (*l < 0) ? state : NULL;
struct atmarp_entry *entry = NEIGH2ENTRY(n); }
struct clip_vcc *vcc;
if (!entry->vccs) { static void *arp_get_idx(struct arp_state *state, loff_t l)
if (--count) continue; {
atmarp_info(n->dev,entry,NULL,buf); void *v = NULL;
read_unlock_bh(&clip_tbl_hook->lock);
module_put(atm_clip_ops->owner); for (; state->bucket <= NEIGH_HASHMASK; state->bucket++) {
return strlen(buf); for (; state->n; state->n = state->n->next) {
v = arp_vcc_walk(state, NEIGH2ENTRY(state->n), &l);
if (v)
goto done;
} }
for (vcc = entry->vccs; vcc; state->n = clip_tbl_hook->hash_buckets[state->bucket + 1];
vcc = vcc->next) {
if (--count) continue;
atmarp_info(n->dev,entry,vcc,buf);
read_unlock_bh(&clip_tbl_hook->lock);
module_put(atm_clip_ops->owner);
return strlen(buf);
} }
done:
return v;
}
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);
state->bucket = 0;
state->n = clip_tbl_hook->hash_buckets[0];
state->vcc = (void *)1;
if (*pos)
ret = arp_get_idx(state, *pos);
out:
return ret;
}
static void arp_seq_stop(struct seq_file *seq, void *v)
{
struct arp_state *state = seq->private;
if (state->bucket != -1)
read_unlock_bh(&clip_tbl_hook->lock); 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)
{
struct arp_state *state = seq->private;
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; return 0;
} }
#endif
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);
out_kfree:
kfree(state);
goto out;
}
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