Commit 32f6c4ce authored by Chas Williams's avatar Chas Williams Committed by David S. Miller

[ATM]: Convert VCC list to hash.

parent f31153ad
...@@ -158,6 +158,7 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) ...@@ -158,6 +158,7 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
struct atm_vcc *vcc; struct atm_vcc *vcc;
struct hlist_node *node; struct hlist_node *node;
struct sock *s; struct sock *s;
int i;
if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD; if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT; if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
...@@ -166,7 +167,10 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) ...@@ -166,7 +167,10 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 || if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL; ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) { for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
sk_for_each(s, node, head) {
vcc = atm_sk(s); vcc = atm_sk(s);
if (vcc->dev != dev) if (vcc->dev != dev)
continue; continue;
...@@ -176,6 +180,7 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) ...@@ -176,6 +180,7 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
return -EBUSY; return -EBUSY;
} }
} }
}
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
dev->ci_range = ci; dev->ci_range = ci;
return 0; return 0;
...@@ -244,6 +249,7 @@ static void atmtcp_c_close(struct atm_vcc *vcc) ...@@ -244,6 +249,7 @@ static void atmtcp_c_close(struct atm_vcc *vcc)
struct sock *s; struct sock *s;
struct hlist_node *node; struct hlist_node *node;
struct atm_vcc *walk; struct atm_vcc *walk;
int i;
atmtcp_dev = (struct atm_dev *) vcc->dev_data; atmtcp_dev = (struct atm_dev *) vcc->dev_data;
dev_data = PRIV(atmtcp_dev); dev_data = PRIV(atmtcp_dev);
...@@ -254,12 +260,16 @@ static void atmtcp_c_close(struct atm_vcc *vcc) ...@@ -254,12 +260,16 @@ static void atmtcp_c_close(struct atm_vcc *vcc)
shutdown_atm_dev(atmtcp_dev); shutdown_atm_dev(atmtcp_dev);
vcc->dev_data = NULL; vcc->dev_data = NULL;
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) { for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
sk_for_each(s, node, head) {
walk = atm_sk(s); walk = atm_sk(s);
if (walk->dev != atmtcp_dev) if (walk->dev != atmtcp_dev)
continue; continue;
wake_up(walk->sk->sk_sleep); wake_up(walk->sk->sk_sleep);
} }
}
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
} }
...@@ -272,7 +282,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) ...@@ -272,7 +282,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
struct hlist_node *node; struct hlist_node *node;
struct atm_vcc *out_vcc = NULL; struct atm_vcc *out_vcc = NULL;
struct sk_buff *new_skb; struct sk_buff *new_skb;
int result = 0; int i, result = 0;
if (!skb->len) return 0; if (!skb->len) return 0;
dev = vcc->dev_data; dev = vcc->dev_data;
...@@ -283,7 +293,10 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) ...@@ -283,7 +293,10 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
goto done; goto done;
} }
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) { for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
sk_for_each(s, node, head) {
out_vcc = atm_sk(s); out_vcc = atm_sk(s);
if (out_vcc->dev != dev) if (out_vcc->dev != dev)
continue; continue;
...@@ -292,6 +305,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) ...@@ -292,6 +305,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
out_vcc->qos.rxtp.traffic_class != ATM_NONE) out_vcc->qos.rxtp.traffic_class != ATM_NONE)
break; break;
} }
}
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
if (!out_vcc) { if (!out_vcc) {
atomic_inc(&vcc->stats->tx_err); atomic_inc(&vcc->stats->tx_err);
......
...@@ -2147,7 +2147,10 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) ...@@ -2147,7 +2147,10 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
skb_queue_len(&tx->backlog)); skb_queue_len(&tx->backlog));
} }
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) { for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
sk_for_each(s, node, head) {
struct eni_vcc *eni_vcc; struct eni_vcc *eni_vcc;
int length; int length;
...@@ -2172,6 +2175,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) ...@@ -2172,6 +2175,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
return length+1; return length+1;
} }
}
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
for (i = 0; i < eni_dev->free_len; i++) { for (i = 0; i < eni_dev->free_len; i++) {
struct eni_free *fe = eni_dev->free_list+i; struct eni_free *fe = eni_dev->free_list+i;
......
...@@ -1071,9 +1071,11 @@ fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd) ...@@ -1071,9 +1071,11 @@ fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
struct sock *s; struct sock *s;
struct atm_vcc* vcc; struct atm_vcc* vcc;
struct hlist_node *node; struct hlist_node *node;
int i;
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) {
sk_for_each(s, node, &vcc_hash[rpd->atm_header.vci & (VCC_HTABLE_SIZE-1)]) {
vcc = atm_sk(s); vcc = atm_sk(s);
if (vcc->dev != fore200e->atm_dev) if (vcc->dev != fore200e->atm_dev)
continue; continue;
...@@ -2606,7 +2608,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) ...@@ -2606,7 +2608,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
struct sock *s; struct sock *s;
struct hlist_node *node; struct hlist_node *node;
struct fore200e* fore200e = FORE200E_DEV(dev); struct fore200e* fore200e = FORE200E_DEV(dev);
int len, left = *pos; int i, len, left = *pos;
if (!left--) { if (!left--) {
...@@ -2852,7 +2854,10 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) ...@@ -2852,7 +2854,10 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
" VCCs:\n address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n"); " VCCs:\n address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n");
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) { for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
sk_for_each(s, node, head) {
vcc = atm_sk(s); vcc = atm_sk(s);
if (vcc->dev != fore200e->atm_dev) if (vcc->dev != fore200e->atm_dev)
...@@ -2870,6 +2875,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) ...@@ -2870,6 +2875,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
fore200e_vcc->rx_max_pdu fore200e_vcc->rx_max_pdu
); );
} }
}
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
return len; return len;
......
...@@ -327,6 +327,7 @@ he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags) ...@@ -327,6 +327,7 @@ he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
static __inline__ struct atm_vcc* static __inline__ struct atm_vcc*
__find_vcc(struct he_dev *he_dev, unsigned cid) __find_vcc(struct he_dev *he_dev, unsigned cid)
{ {
struct hlist_head *head;
struct atm_vcc *vcc; struct atm_vcc *vcc;
struct hlist_node *node; struct hlist_node *node;
struct sock *s; struct sock *s;
...@@ -335,8 +336,9 @@ __find_vcc(struct he_dev *he_dev, unsigned cid) ...@@ -335,8 +336,9 @@ __find_vcc(struct he_dev *he_dev, unsigned cid)
vpi = cid >> he_dev->vcibits; vpi = cid >> he_dev->vcibits;
vci = cid & ((1 << he_dev->vcibits) - 1); vci = cid & ((1 << he_dev->vcibits) - 1);
head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
sk_for_each(s, node, &vcc_sklist) { sk_for_each(s, node, head) {
vcc = atm_sk(s); vcc = atm_sk(s);
if (vcc->dev == he_dev->atm_dev && if (vcc->dev == he_dev->atm_dev &&
vcc->vci == vci && vcc->vpi == vpi && vcc->vci == vci && vcc->vpi == vpi &&
......
...@@ -380,7 +380,9 @@ struct atm_skb_data { ...@@ -380,7 +380,9 @@ struct atm_skb_data {
unsigned long atm_options; /* ATM layer options */ unsigned long atm_options; /* ATM layer options */
}; };
extern struct hlist_head vcc_sklist; #define VCC_HTABLE_SIZE 32
extern struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
extern rwlock_t vcc_sklist_lock; extern rwlock_t vcc_sklist_lock;
#define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb)) #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
......
...@@ -38,13 +38,16 @@ ...@@ -38,13 +38,16 @@
#define DPRINTK(format,args...) #define DPRINTK(format,args...)
#endif #endif
struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
HLIST_HEAD(vcc_sklist);
rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED; rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED;
void __vcc_insert_socket(struct sock *sk) void __vcc_insert_socket(struct sock *sk)
{ {
sk_add_node(sk, &vcc_sklist); struct atm_vcc *vcc = atm_sk(sk);
struct hlist_head *head = &vcc_hash[vcc->vci &
(VCC_HTABLE_SIZE - 1)];
sk->sk_hashent = vcc->vci & (VCC_HTABLE_SIZE - 1);
sk_add_node(sk, head);
} }
void vcc_insert_socket(struct sock *sk) void vcc_insert_socket(struct sock *sk)
...@@ -80,7 +83,7 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size) ...@@ -80,7 +83,7 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
} }
EXPORT_SYMBOL(vcc_sklist); EXPORT_SYMBOL(vcc_hash);
EXPORT_SYMBOL(vcc_sklist_lock); EXPORT_SYMBOL(vcc_sklist_lock);
EXPORT_SYMBOL(vcc_insert_socket); EXPORT_SYMBOL(vcc_insert_socket);
EXPORT_SYMBOL(vcc_remove_socket); EXPORT_SYMBOL(vcc_remove_socket);
...@@ -250,11 +253,13 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) ...@@ -250,11 +253,13 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
static int check_ci(struct atm_vcc *vcc, short vpi, int vci) static int check_ci(struct atm_vcc *vcc, short vpi, int vci)
{ {
struct hlist_head *head = &vcc_hash[vci &
(VCC_HTABLE_SIZE - 1)];
struct hlist_node *node; struct hlist_node *node;
struct sock *s; struct sock *s;
struct atm_vcc *walk; struct atm_vcc *walk;
sk_for_each(s, node, &vcc_sklist) { sk_for_each(s, node, head) {
walk = atm_sk(s); walk = atm_sk(s);
if (walk->dev != vcc->dev) if (walk->dev != vcc->dev)
continue; continue;
......
...@@ -64,6 +64,7 @@ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev) ...@@ -64,6 +64,7 @@ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev)
} }
struct vcc_state { struct vcc_state {
int bucket;
struct sock *sk; struct sock *sk;
int family; int family;
}; };
...@@ -75,19 +76,30 @@ static inline int compare_family(struct sock *sk, int family) ...@@ -75,19 +76,30 @@ static inline int compare_family(struct sock *sk, int family)
return !family || (vcc->sk->sk_family == family); return !family || (vcc->sk->sk_family == family);
} }
static int __vcc_walk(struct sock **sock, int family, loff_t l) static int __vcc_walk(struct sock **sock, int family, int *bucket, loff_t l)
{ {
struct sock *sk = *sock; struct sock *sk = *sock;
if (sk == (void *)1) { if (sk == (void *)1) {
sk = hlist_empty(&vcc_sklist) ? NULL : __sk_head(&vcc_sklist); for (*bucket = 0; *bucket < VCC_HTABLE_SIZE; ++*bucket) {
struct hlist_head *head = &vcc_hash[*bucket];
sk = hlist_empty(head) ? NULL : __sk_head(head);
if (sk)
break;
}
l--; l--;
} }
try_again:
for (; sk; sk = sk_next(sk)) { for (; sk; sk = sk_next(sk)) {
l -= compare_family(sk, family); l -= compare_family(sk, family);
if (l < 0) if (l < 0)
goto out; goto out;
} }
if (!sk && ++*bucket < VCC_HTABLE_SIZE) {
sk = sk_head(&vcc_hash[*bucket]);
goto try_again;
}
sk = (void *)1; sk = (void *)1;
out: out:
*sock = sk; *sock = sk;
...@@ -96,7 +108,7 @@ static int __vcc_walk(struct sock **sock, int family, loff_t l) ...@@ -96,7 +108,7 @@ static int __vcc_walk(struct sock **sock, int family, loff_t l)
static inline void *vcc_walk(struct vcc_state *state, loff_t l) static inline void *vcc_walk(struct vcc_state *state, loff_t l)
{ {
return __vcc_walk(&state->sk, state->family, l) ? return __vcc_walk(&state->sk, state->family, &state->bucket, l) ?
state : NULL; state : NULL;
} }
...@@ -207,9 +219,10 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc) ...@@ -207,9 +219,10 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
default: default:
seq_printf(seq, "%3d", vcc->sk->sk_family); seq_printf(seq, "%3d", vcc->sk->sk_family);
} }
seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d\n", vcc->flags, vcc->sk->sk_err, seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d] 0x%x\n", vcc->flags, vcc->sk->sk_err,
atomic_read(&vcc->sk->sk_wmem_alloc),vcc->sk->sk_sndbuf, atomic_read(&vcc->sk->sk_wmem_alloc),vcc->sk->sk_sndbuf,
atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf); atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf,
atomic_read(&vcc->sk->sk_refcnt), vcc->sk->sk_hashent);
} }
static void svc_info(struct seq_file *seq, struct atm_vcc *vcc) static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
......
...@@ -216,6 +216,7 @@ static void sigd_close(struct atm_vcc *vcc) ...@@ -216,6 +216,7 @@ static void sigd_close(struct atm_vcc *vcc)
{ {
struct hlist_node *node; struct hlist_node *node;
struct sock *s; struct sock *s;
int i;
DPRINTK("sigd_close\n"); DPRINTK("sigd_close\n");
sigd = NULL; sigd = NULL;
...@@ -224,12 +225,16 @@ static void sigd_close(struct atm_vcc *vcc) ...@@ -224,12 +225,16 @@ static void sigd_close(struct atm_vcc *vcc)
skb_queue_purge(&vcc->sk->sk_receive_queue); skb_queue_purge(&vcc->sk->sk_receive_queue);
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
sk_for_each(s, node, &vcc_sklist) { for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
sk_for_each(s, node, head) {
struct atm_vcc *vcc = atm_sk(s); struct atm_vcc *vcc = atm_sk(s);
if (vcc->dev) if (vcc->dev)
purge_vcc(vcc); purge_vcc(vcc);
} }
}
read_unlock(&vcc_sklist_lock); read_unlock(&vcc_sklist_lock);
} }
......
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