Convert the custom hash list traversals to use hlist functions.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
return (h & (sctp_assoc_hashsize-1));
}
+#define sctp_for_each_hentry(epb, node, head) \
+ hlist_for_each_entry(epb, node, head, node)
+
/* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style)
struct sctp_bind_bucket {
unsigned short port;
unsigned short fastreuse;
- struct sctp_bind_bucket *next;
- struct sctp_bind_bucket **pprev;
+ struct hlist_node node;
struct hlist_head owner;
};
struct sctp_bind_hashbucket {
spinlock_t lock;
- struct sctp_bind_bucket *chain;
+ struct hlist_head chain;
};
/* Used for hashing all associations. */
struct sctp_hashbucket {
rwlock_t lock;
- struct sctp_ep_common *chain;
+ struct hlist_head chain;
} __attribute__((__aligned__(8)));
struct sctp_ep_common {
/* Fields to help us manage our entries in the hash tables. */
- struct sctp_ep_common *next;
- struct sctp_ep_common **pprev;
+ struct hlist_node node;
int hashent;
/* Runtime type information. What kind of endpoint is this? */
struct sctp_transport *t = NULL;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
+ struct hlist_node *node;
int hash;
int rport;
hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
asoc = sctp_assoc(epb);
if (asoc->ep != ep || rport != asoc->peer.port)
goto next;
/* Insert endpoint into the hash table. */
static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
- struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- epp = &head->chain;
- epb->next = *epp;
- if (epb->next)
- (*epp)->pprev = &epb->next;
- *epp = epb;
- epb->pprev = epp;
+ hlist_add_head(&epb->node, &head->chain);
sctp_write_unlock(&head->lock);
}
epb = &ep->base;
+ if (hlist_unhashed(&epb->node))
+ return;
+
epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
-
- if (epb->pprev) {
- if (epb->next)
- epb->next->pprev = epb->pprev;
- *epb->pprev = epb->next;
- epb->pprev = NULL;
- }
-
+ __hlist_del(&epb->node);
sctp_write_unlock(&head->lock);
}
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
+ struct hlist_node *node;
int hash;
hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
head = &sctp_ep_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
if (sctp_endpoint_is_match(ep, laddr))
goto hit;
/* Insert association into the hash table. */
static void __sctp_hash_established(struct sctp_association *asoc)
{
- struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- epp = &head->chain;
- epb->next = *epp;
- if (epb->next)
- (*epp)->pprev = &epb->next;
- *epp = epb;
- epb->pprev = epp;
+ hlist_add_head(&epb->node, &head->chain);
sctp_write_unlock(&head->lock);
}
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
-
- if (epb->pprev) {
- if (epb->next)
- epb->next->pprev = epb->pprev;
- *epb->pprev = epb->next;
- epb->pprev = NULL;
- }
-
+ __hlist_del(&epb->node);
sctp_write_unlock(&head->lock);
}
struct sctp_ep_common *epb;
struct sctp_association *asoc;
struct sctp_transport *transport;
+ struct hlist_node *node;
int hash;
/* Optimize here for direct hit, only listening connections can
hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
asoc = sctp_assoc(epb);
transport = sctp_assoc_is_match(asoc, local, peer);
if (transport)
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
struct sock *sk;
+ struct hlist_node *node;
int hash = *(loff_t *)v;
if (hash >= sctp_ep_hashsize)
head = &sctp_ep_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
sk = epb->sk;
seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
struct sctp_ep_common *epb;
struct sctp_association *assoc;
struct sock *sk;
+ struct hlist_node *node;
int hash = *(loff_t *)v;
if (hash >= sctp_assoc_hashsize)
head = &sctp_assoc_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
assoc = sctp_assoc(epb);
sk = epb->sk;
seq_printf(seq,
}
for (i = 0; i < sctp_assoc_hashsize; i++) {
rwlock_init(&sctp_assoc_hashtable[i].lock);
- sctp_assoc_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain);
}
/* Allocate and initialize the endpoint hash table. */
}
for (i = 0; i < sctp_ep_hashsize; i++) {
rwlock_init(&sctp_ep_hashtable[i].lock);
- sctp_ep_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
}
/* Allocate and initialize the SCTP port hash table. */
}
for (i = 0; i < sctp_port_hashsize; i++) {
spin_lock_init(&sctp_port_hashtable[i].lock);
- sctp_port_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
}
printk(KERN_INFO "SCTP: Hash tables configured "
{
struct sctp_bind_hashbucket *head; /* hash list */
struct sctp_bind_bucket *pp; /* hash list port iterator */
+ struct hlist_node *node;
unsigned short snum;
int ret;
index = sctp_phashfn(rover);
head = &sctp_port_hashtable[index];
sctp_spin_lock(&head->lock);
- for (pp = head->chain; pp; pp = pp->next)
+ sctp_for_each_hentry(pp, node, &head->chain)
if (pp->port == rover)
goto next;
break;
*/
head = &sctp_port_hashtable[sctp_phashfn(snum)];
sctp_spin_lock(&head->lock);
- for (pp = head->chain; pp; pp = pp->next) {
+ sctp_for_each_hentry(pp, node, &head->chain) {
if (pp->port == snum)
goto pp_found;
}
pp->port = snum;
pp->fastreuse = 0;
INIT_HLIST_HEAD(&pp->owner);
- if ((pp->next = head->chain) != NULL)
- pp->next->pprev = &pp->next;
- head->chain = pp;
- pp->pprev = &head->chain;
+ hlist_add_head(&pp->node, &head->chain);
}
return pp;
}
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
if (pp && hlist_empty(&pp->owner)) {
- if (pp->next)
- pp->next->pprev = pp->pprev;
- *(pp->pprev) = pp->next;
+ __hlist_del(&pp->node);
kmem_cache_free(sctp_bucket_cachep, pp);
SCTP_DBG_OBJCNT_DEC(bind_bucket);
}