diff options
-rw-r--r-- | include/net/sctp/sctp.h | 3 | ||||
-rw-r--r-- | include/net/sctp/structs.h | 10 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 3 | ||||
-rw-r--r-- | net/sctp/input.c | 43 | ||||
-rw-r--r-- | net/sctp/proc.c | 6 | ||||
-rw-r--r-- | net/sctp/protocol.c | 6 | ||||
-rw-r--r-- | net/sctp/socket.c | 14 |
7 files changed, 32 insertions, 53 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 70827305f501..67c997cecf58 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -665,6 +665,9 @@ static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) | |||
665 | return (h & (sctp_assoc_hashsize-1)); | 665 | return (h & (sctp_assoc_hashsize-1)); |
666 | } | 666 | } |
667 | 667 | ||
668 | #define sctp_for_each_hentry(epb, node, head) \ | ||
669 | hlist_for_each_entry(epb, node, head, node) | ||
670 | |||
668 | /* Is a socket of this style? */ | 671 | /* Is a socket of this style? */ |
669 | #define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) | 672 | #define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) |
670 | static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style) | 673 | static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style) |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 44f2672859e2..eb3113c38a94 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -100,20 +100,19 @@ struct crypto_hash; | |||
100 | struct sctp_bind_bucket { | 100 | struct sctp_bind_bucket { |
101 | unsigned short port; | 101 | unsigned short port; |
102 | unsigned short fastreuse; | 102 | unsigned short fastreuse; |
103 | struct sctp_bind_bucket *next; | 103 | struct hlist_node node; |
104 | struct sctp_bind_bucket **pprev; | ||
105 | struct hlist_head owner; | 104 | struct hlist_head owner; |
106 | }; | 105 | }; |
107 | 106 | ||
108 | struct sctp_bind_hashbucket { | 107 | struct sctp_bind_hashbucket { |
109 | spinlock_t lock; | 108 | spinlock_t lock; |
110 | struct sctp_bind_bucket *chain; | 109 | struct hlist_head chain; |
111 | }; | 110 | }; |
112 | 111 | ||
113 | /* Used for hashing all associations. */ | 112 | /* Used for hashing all associations. */ |
114 | struct sctp_hashbucket { | 113 | struct sctp_hashbucket { |
115 | rwlock_t lock; | 114 | rwlock_t lock; |
116 | struct sctp_ep_common *chain; | 115 | struct hlist_head chain; |
117 | } __attribute__((__aligned__(8))); | 116 | } __attribute__((__aligned__(8))); |
118 | 117 | ||
119 | 118 | ||
@@ -1230,8 +1229,7 @@ typedef enum { | |||
1230 | 1229 | ||
1231 | struct sctp_ep_common { | 1230 | struct sctp_ep_common { |
1232 | /* Fields to help us manage our entries in the hash tables. */ | 1231 | /* Fields to help us manage our entries in the hash tables. */ |
1233 | struct sctp_ep_common *next; | 1232 | struct hlist_node node; |
1234 | struct sctp_ep_common **pprev; | ||
1235 | int hashent; | 1233 | int hashent; |
1236 | 1234 | ||
1237 | /* Runtime type information. What kind of endpoint is this? */ | 1235 | /* Runtime type information. What kind of endpoint is this? */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 68f0556efcc6..de6f505d6ff8 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -332,6 +332,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
332 | struct sctp_transport *t = NULL; | 332 | struct sctp_transport *t = NULL; |
333 | struct sctp_hashbucket *head; | 333 | struct sctp_hashbucket *head; |
334 | struct sctp_ep_common *epb; | 334 | struct sctp_ep_common *epb; |
335 | struct hlist_node *node; | ||
335 | int hash; | 336 | int hash; |
336 | int rport; | 337 | int rport; |
337 | 338 | ||
@@ -341,7 +342,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
341 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); | 342 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); |
342 | head = &sctp_assoc_hashtable[hash]; | 343 | head = &sctp_assoc_hashtable[hash]; |
343 | read_lock(&head->lock); | 344 | read_lock(&head->lock); |
344 | for (epb = head->chain; epb; epb = epb->next) { | 345 | sctp_for_each_hentry(epb, node, &head->chain) { |
345 | asoc = sctp_assoc(epb); | 346 | asoc = sctp_assoc(epb); |
346 | if (asoc->ep != ep || rport != asoc->peer.port) | 347 | if (asoc->ep != ep || rport != asoc->peer.port) |
347 | goto next; | 348 | goto next; |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 86503e7fa21e..91ae463b079b 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -656,7 +656,6 @@ discard: | |||
656 | /* Insert endpoint into the hash table. */ | 656 | /* Insert endpoint into the hash table. */ |
657 | static void __sctp_hash_endpoint(struct sctp_endpoint *ep) | 657 | static void __sctp_hash_endpoint(struct sctp_endpoint *ep) |
658 | { | 658 | { |
659 | struct sctp_ep_common **epp; | ||
660 | struct sctp_ep_common *epb; | 659 | struct sctp_ep_common *epb; |
661 | struct sctp_hashbucket *head; | 660 | struct sctp_hashbucket *head; |
662 | 661 | ||
@@ -666,12 +665,7 @@ static void __sctp_hash_endpoint(struct sctp_endpoint *ep) | |||
666 | head = &sctp_ep_hashtable[epb->hashent]; | 665 | head = &sctp_ep_hashtable[epb->hashent]; |
667 | 666 | ||
668 | sctp_write_lock(&head->lock); | 667 | sctp_write_lock(&head->lock); |
669 | epp = &head->chain; | 668 | hlist_add_head(&epb->node, &head->chain); |
670 | epb->next = *epp; | ||
671 | if (epb->next) | ||
672 | (*epp)->pprev = &epb->next; | ||
673 | *epp = epb; | ||
674 | epb->pprev = epp; | ||
675 | sctp_write_unlock(&head->lock); | 669 | sctp_write_unlock(&head->lock); |
676 | } | 670 | } |
677 | 671 | ||
@@ -691,19 +685,15 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) | |||
691 | 685 | ||
692 | epb = &ep->base; | 686 | epb = &ep->base; |
693 | 687 | ||
688 | if (hlist_unhashed(&epb->node)) | ||
689 | return; | ||
690 | |||
694 | epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); | 691 | epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); |
695 | 692 | ||
696 | head = &sctp_ep_hashtable[epb->hashent]; | 693 | head = &sctp_ep_hashtable[epb->hashent]; |
697 | 694 | ||
698 | sctp_write_lock(&head->lock); | 695 | sctp_write_lock(&head->lock); |
699 | 696 | __hlist_del(&epb->node); | |
700 | if (epb->pprev) { | ||
701 | if (epb->next) | ||
702 | epb->next->pprev = epb->pprev; | ||
703 | *epb->pprev = epb->next; | ||
704 | epb->pprev = NULL; | ||
705 | } | ||
706 | |||
707 | sctp_write_unlock(&head->lock); | 697 | sctp_write_unlock(&head->lock); |
708 | } | 698 | } |
709 | 699 | ||
@@ -721,12 +711,13 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l | |||
721 | struct sctp_hashbucket *head; | 711 | struct sctp_hashbucket *head; |
722 | struct sctp_ep_common *epb; | 712 | struct sctp_ep_common *epb; |
723 | struct sctp_endpoint *ep; | 713 | struct sctp_endpoint *ep; |
714 | struct hlist_node *node; | ||
724 | int hash; | 715 | int hash; |
725 | 716 | ||
726 | hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); | 717 | hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); |
727 | head = &sctp_ep_hashtable[hash]; | 718 | head = &sctp_ep_hashtable[hash]; |
728 | read_lock(&head->lock); | 719 | read_lock(&head->lock); |
729 | for (epb = head->chain; epb; epb = epb->next) { | 720 | sctp_for_each_hentry(epb, node, &head->chain) { |
730 | ep = sctp_ep(epb); | 721 | ep = sctp_ep(epb); |
731 | if (sctp_endpoint_is_match(ep, laddr)) | 722 | if (sctp_endpoint_is_match(ep, laddr)) |
732 | goto hit; | 723 | goto hit; |
@@ -744,7 +735,6 @@ hit: | |||
744 | /* Insert association into the hash table. */ | 735 | /* Insert association into the hash table. */ |
745 | static void __sctp_hash_established(struct sctp_association *asoc) | 736 | static void __sctp_hash_established(struct sctp_association *asoc) |
746 | { | 737 | { |
747 | struct sctp_ep_common **epp; | ||
748 | struct sctp_ep_common *epb; | 738 | struct sctp_ep_common *epb; |
749 | struct sctp_hashbucket *head; | 739 | struct sctp_hashbucket *head; |
750 | 740 | ||
@@ -756,12 +746,7 @@ static void __sctp_hash_established(struct sctp_association *asoc) | |||
756 | head = &sctp_assoc_hashtable[epb->hashent]; | 746 | head = &sctp_assoc_hashtable[epb->hashent]; |
757 | 747 | ||
758 | sctp_write_lock(&head->lock); | 748 | sctp_write_lock(&head->lock); |
759 | epp = &head->chain; | 749 | hlist_add_head(&epb->node, &head->chain); |
760 | epb->next = *epp; | ||
761 | if (epb->next) | ||
762 | (*epp)->pprev = &epb->next; | ||
763 | *epp = epb; | ||
764 | epb->pprev = epp; | ||
765 | sctp_write_unlock(&head->lock); | 750 | sctp_write_unlock(&head->lock); |
766 | } | 751 | } |
767 | 752 | ||
@@ -790,14 +775,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) | |||
790 | head = &sctp_assoc_hashtable[epb->hashent]; | 775 | head = &sctp_assoc_hashtable[epb->hashent]; |
791 | 776 | ||
792 | sctp_write_lock(&head->lock); | 777 | sctp_write_lock(&head->lock); |
793 | 778 | __hlist_del(&epb->node); | |
794 | if (epb->pprev) { | ||
795 | if (epb->next) | ||
796 | epb->next->pprev = epb->pprev; | ||
797 | *epb->pprev = epb->next; | ||
798 | epb->pprev = NULL; | ||
799 | } | ||
800 | |||
801 | sctp_write_unlock(&head->lock); | 779 | sctp_write_unlock(&head->lock); |
802 | } | 780 | } |
803 | 781 | ||
@@ -822,6 +800,7 @@ static struct sctp_association *__sctp_lookup_association( | |||
822 | struct sctp_ep_common *epb; | 800 | struct sctp_ep_common *epb; |
823 | struct sctp_association *asoc; | 801 | struct sctp_association *asoc; |
824 | struct sctp_transport *transport; | 802 | struct sctp_transport *transport; |
803 | struct hlist_node *node; | ||
825 | int hash; | 804 | int hash; |
826 | 805 | ||
827 | /* Optimize here for direct hit, only listening connections can | 806 | /* Optimize here for direct hit, only listening connections can |
@@ -830,7 +809,7 @@ static struct sctp_association *__sctp_lookup_association( | |||
830 | hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); | 809 | hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); |
831 | head = &sctp_assoc_hashtable[hash]; | 810 | head = &sctp_assoc_hashtable[hash]; |
832 | read_lock(&head->lock); | 811 | read_lock(&head->lock); |
833 | for (epb = head->chain; epb; epb = epb->next) { | 812 | sctp_for_each_hentry(epb, node, &head->chain) { |
834 | asoc = sctp_assoc(epb); | 813 | asoc = sctp_assoc(epb); |
835 | transport = sctp_assoc_is_match(asoc, local, peer); | 814 | transport = sctp_assoc_is_match(asoc, local, peer); |
836 | if (transport) | 815 | if (transport) |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index e4cd841a22e4..249973204070 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -225,6 +225,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
225 | struct sctp_ep_common *epb; | 225 | struct sctp_ep_common *epb; |
226 | struct sctp_endpoint *ep; | 226 | struct sctp_endpoint *ep; |
227 | struct sock *sk; | 227 | struct sock *sk; |
228 | struct hlist_node *node; | ||
228 | int hash = *(loff_t *)v; | 229 | int hash = *(loff_t *)v; |
229 | 230 | ||
230 | if (hash >= sctp_ep_hashsize) | 231 | if (hash >= sctp_ep_hashsize) |
@@ -233,7 +234,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
233 | head = &sctp_ep_hashtable[hash]; | 234 | head = &sctp_ep_hashtable[hash]; |
234 | sctp_local_bh_disable(); | 235 | sctp_local_bh_disable(); |
235 | read_lock(&head->lock); | 236 | read_lock(&head->lock); |
236 | for (epb = head->chain; epb; epb = epb->next) { | 237 | sctp_for_each_hentry(epb, node, &head->chain) { |
237 | ep = sctp_ep(epb); | 238 | ep = sctp_ep(epb); |
238 | sk = epb->sk; | 239 | sk = epb->sk; |
239 | seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, | 240 | seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, |
@@ -328,6 +329,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
328 | struct sctp_ep_common *epb; | 329 | struct sctp_ep_common *epb; |
329 | struct sctp_association *assoc; | 330 | struct sctp_association *assoc; |
330 | struct sock *sk; | 331 | struct sock *sk; |
332 | struct hlist_node *node; | ||
331 | int hash = *(loff_t *)v; | 333 | int hash = *(loff_t *)v; |
332 | 334 | ||
333 | if (hash >= sctp_assoc_hashsize) | 335 | if (hash >= sctp_assoc_hashsize) |
@@ -336,7 +338,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
336 | head = &sctp_assoc_hashtable[hash]; | 338 | head = &sctp_assoc_hashtable[hash]; |
337 | sctp_local_bh_disable(); | 339 | sctp_local_bh_disable(); |
338 | read_lock(&head->lock); | 340 | read_lock(&head->lock); |
339 | for (epb = head->chain; epb; epb = epb->next) { | 341 | sctp_for_each_hentry(epb, node, &head->chain) { |
340 | assoc = sctp_assoc(epb); | 342 | assoc = sctp_assoc(epb); |
341 | sk = epb->sk; | 343 | sk = epb->sk; |
342 | seq_printf(seq, | 344 | seq_printf(seq, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index ecfab0344e73..d50f610d1b02 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1137,7 +1137,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1137 | } | 1137 | } |
1138 | for (i = 0; i < sctp_assoc_hashsize; i++) { | 1138 | for (i = 0; i < sctp_assoc_hashsize; i++) { |
1139 | rwlock_init(&sctp_assoc_hashtable[i].lock); | 1139 | rwlock_init(&sctp_assoc_hashtable[i].lock); |
1140 | sctp_assoc_hashtable[i].chain = NULL; | 1140 | INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain); |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | /* Allocate and initialize the endpoint hash table. */ | 1143 | /* Allocate and initialize the endpoint hash table. */ |
@@ -1151,7 +1151,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1151 | } | 1151 | } |
1152 | for (i = 0; i < sctp_ep_hashsize; i++) { | 1152 | for (i = 0; i < sctp_ep_hashsize; i++) { |
1153 | rwlock_init(&sctp_ep_hashtable[i].lock); | 1153 | rwlock_init(&sctp_ep_hashtable[i].lock); |
1154 | sctp_ep_hashtable[i].chain = NULL; | 1154 | INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | /* Allocate and initialize the SCTP port hash table. */ | 1157 | /* Allocate and initialize the SCTP port hash table. */ |
@@ -1170,7 +1170,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1170 | } | 1170 | } |
1171 | for (i = 0; i < sctp_port_hashsize; i++) { | 1171 | for (i = 0; i < sctp_port_hashsize; i++) { |
1172 | spin_lock_init(&sctp_port_hashtable[i].lock); | 1172 | spin_lock_init(&sctp_port_hashtable[i].lock); |
1173 | sctp_port_hashtable[i].chain = NULL; | 1173 | INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | printk(KERN_INFO "SCTP: Hash tables configured " | 1176 | printk(KERN_INFO "SCTP: Hash tables configured " |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6ce9b490fad5..ff8bc95670ed 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5307,6 +5307,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5307 | { | 5307 | { |
5308 | struct sctp_bind_hashbucket *head; /* hash list */ | 5308 | struct sctp_bind_hashbucket *head; /* hash list */ |
5309 | struct sctp_bind_bucket *pp; /* hash list port iterator */ | 5309 | struct sctp_bind_bucket *pp; /* hash list port iterator */ |
5310 | struct hlist_node *node; | ||
5310 | unsigned short snum; | 5311 | unsigned short snum; |
5311 | int ret; | 5312 | int ret; |
5312 | 5313 | ||
@@ -5331,7 +5332,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5331 | index = sctp_phashfn(rover); | 5332 | index = sctp_phashfn(rover); |
5332 | head = &sctp_port_hashtable[index]; | 5333 | head = &sctp_port_hashtable[index]; |
5333 | sctp_spin_lock(&head->lock); | 5334 | sctp_spin_lock(&head->lock); |
5334 | for (pp = head->chain; pp; pp = pp->next) | 5335 | sctp_for_each_hentry(pp, node, &head->chain) |
5335 | if (pp->port == rover) | 5336 | if (pp->port == rover) |
5336 | goto next; | 5337 | goto next; |
5337 | break; | 5338 | break; |
@@ -5358,7 +5359,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5358 | */ | 5359 | */ |
5359 | head = &sctp_port_hashtable[sctp_phashfn(snum)]; | 5360 | head = &sctp_port_hashtable[sctp_phashfn(snum)]; |
5360 | sctp_spin_lock(&head->lock); | 5361 | sctp_spin_lock(&head->lock); |
5361 | for (pp = head->chain; pp; pp = pp->next) { | 5362 | sctp_for_each_hentry(pp, node, &head->chain) { |
5362 | if (pp->port == snum) | 5363 | if (pp->port == snum) |
5363 | goto pp_found; | 5364 | goto pp_found; |
5364 | } | 5365 | } |
@@ -5702,10 +5703,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
5702 | pp->port = snum; | 5703 | pp->port = snum; |
5703 | pp->fastreuse = 0; | 5704 | pp->fastreuse = 0; |
5704 | INIT_HLIST_HEAD(&pp->owner); | 5705 | INIT_HLIST_HEAD(&pp->owner); |
5705 | if ((pp->next = head->chain) != NULL) | 5706 | hlist_add_head(&pp->node, &head->chain); |
5706 | pp->next->pprev = &pp->next; | ||
5707 | head->chain = pp; | ||
5708 | pp->pprev = &head->chain; | ||
5709 | } | 5707 | } |
5710 | return pp; | 5708 | return pp; |
5711 | } | 5709 | } |
@@ -5714,9 +5712,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
5714 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) | 5712 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) |
5715 | { | 5713 | { |
5716 | if (pp && hlist_empty(&pp->owner)) { | 5714 | if (pp && hlist_empty(&pp->owner)) { |
5717 | if (pp->next) | 5715 | __hlist_del(&pp->node); |
5718 | pp->next->pprev = pp->pprev; | ||
5719 | *(pp->pprev) = pp->next; | ||
5720 | kmem_cache_free(sctp_bucket_cachep, pp); | 5716 | kmem_cache_free(sctp_bucket_cachep, pp); |
5721 | SCTP_DBG_OBJCNT_DEC(bind_bucket); | 5717 | SCTP_DBG_OBJCNT_DEC(bind_bucket); |
5722 | } | 5718 | } |