Commit 6708c876 authored by Jon Grimm's avatar Jon Grimm

[SCTP] Use slab cache for sctp_chunk & sctp_bind_bucket.

parent a8feee2c
...@@ -92,24 +92,24 @@ struct sctp_ssnmap; ...@@ -92,24 +92,24 @@ struct sctp_ssnmap;
/* Structures useful for managing bind/connect. */ /* Structures useful for managing bind/connect. */
typedef struct sctp_bind_bucket { struct sctp_bind_bucket {
unsigned short port; unsigned short port;
unsigned short fastreuse; unsigned short fastreuse;
struct sctp_bind_bucket *next; struct sctp_bind_bucket *next;
struct sctp_bind_bucket **pprev; struct sctp_bind_bucket **pprev;
struct sock *sk; struct sock *sk;
} sctp_bind_bucket_t; };
typedef struct sctp_bind_hashbucket { struct sctp_bind_hashbucket {
spinlock_t lock; spinlock_t lock;
struct sctp_bind_bucket *chain; struct sctp_bind_bucket *chain;
} sctp_bind_hashbucket_t; };
/* Used for hashing all associations. */ /* Used for hashing all associations. */
typedef struct sctp_hashbucket { struct sctp_hashbucket {
rwlock_t lock; rwlock_t lock;
struct sctp_ep_common *chain; struct sctp_ep_common *chain;
} sctp_hashbucket_t __attribute__((__aligned__(8))); } __attribute__((__aligned__(8)));
/* The SCTP protocol structure. */ /* The SCTP protocol structure. */
...@@ -167,17 +167,17 @@ struct sctp_protocol { ...@@ -167,17 +167,17 @@ struct sctp_protocol {
/* This is the hash of all endpoints. */ /* This is the hash of all endpoints. */
int ep_hashsize; int ep_hashsize;
sctp_hashbucket_t *ep_hashbucket; struct sctp_hashbucket *ep_hashbucket;
/* This is the hash of all associations. */ /* This is the hash of all associations. */
int assoc_hashsize; int assoc_hashsize;
sctp_hashbucket_t *assoc_hashbucket; struct sctp_hashbucket *assoc_hashbucket;
/* This is the sctp port control hash. */ /* This is the sctp port control hash. */
int port_hashsize; int port_hashsize;
int port_rover; int port_rover;
spinlock_t port_alloc_lock; /* Protects port_rover. */ spinlock_t port_alloc_lock; /* Protects port_rover. */
sctp_bind_hashbucket_t *port_hashtable; struct sctp_bind_hashbucket *port_hashtable;
/* This is the global local address list. /* This is the global local address list.
* We actively maintain this complete list of interfaces on * We actively maintain this complete list of interfaces on
......
...@@ -522,7 +522,7 @@ void __sctp_hash_endpoint(struct sctp_endpoint *ep) ...@@ -522,7 +522,7 @@ void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{ {
struct sctp_ep_common **epp; struct sctp_ep_common **epp;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
epb = &ep->base; epb = &ep->base;
...@@ -550,7 +550,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep) ...@@ -550,7 +550,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
/* Remove endpoint from the hash table. */ /* Remove endpoint from the hash table. */
void __sctp_unhash_endpoint(struct sctp_endpoint *ep) void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
epb = &ep->base; epb = &ep->base;
...@@ -582,7 +582,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep) ...@@ -582,7 +582,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
/* Look up an endpoint. */ /* Look up an endpoint. */
struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr) struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
int hash; int hash;
...@@ -619,7 +619,7 @@ void __sctp_hash_established(struct sctp_association *asoc) ...@@ -619,7 +619,7 @@ void __sctp_hash_established(struct sctp_association *asoc)
{ {
struct sctp_ep_common **epp; struct sctp_ep_common **epp;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
epb = &asoc->base; epb = &asoc->base;
...@@ -649,7 +649,7 @@ void sctp_unhash_established(struct sctp_association *asoc) ...@@ -649,7 +649,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
/* Remove association from the hash table. */ /* Remove association from the hash table. */
void __sctp_unhash_established(struct sctp_association *asoc) void __sctp_unhash_established(struct sctp_association *asoc)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
epb = &asoc->base; epb = &asoc->base;
...@@ -677,7 +677,7 @@ struct sctp_association *__sctp_lookup_association( ...@@ -677,7 +677,7 @@ struct sctp_association *__sctp_lookup_association(
const union sctp_addr *peer, const union sctp_addr *peer,
struct sctp_transport **pt) struct sctp_transport **pt)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
struct sctp_association *asoc; struct sctp_association *asoc;
struct sctp_transport *transport; struct sctp_transport *transport;
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
...@@ -74,6 +74,9 @@ static struct sctp_pf *sctp_pf_inet_specific; ...@@ -74,6 +74,9 @@ static struct sctp_pf *sctp_pf_inet_specific;
static struct sctp_af *sctp_af_v4_specific; static struct sctp_af *sctp_af_v4_specific;
static struct sctp_af *sctp_af_v6_specific; static struct sctp_af *sctp_af_v6_specific;
kmem_cache_t *sctp_chunk_cachep;
kmem_cache_t *sctp_bucket_cachep;
extern struct net_proto_family inet_family_ops; extern struct net_proto_family inet_family_ops;
extern int sctp_snmp_proc_init(void); extern int sctp_snmp_proc_init(void);
...@@ -106,10 +109,12 @@ __init int sctp_proc_init(void) ...@@ -106,10 +109,12 @@ __init int sctp_proc_init(void)
return rc; return rc;
} }
/* Clean up the proc fs entry for the SCTP protocol. */ /* Clean up the proc fs entry for the SCTP protocol.
* Note: Do not make this __exit as it is used in the init error
* path.
*/
void sctp_proc_exit(void) void sctp_proc_exit(void)
{ {
sctp_snmp_proc_exit(); sctp_snmp_proc_exit();
if (proc_net_sctp) { if (proc_net_sctp) {
...@@ -926,6 +931,22 @@ __init int sctp_init(void) ...@@ -926,6 +931,22 @@ __init int sctp_init(void)
inet_register_protosw(&sctp_seqpacket_protosw); inet_register_protosw(&sctp_seqpacket_protosw);
inet_register_protosw(&sctp_stream_protosw); inet_register_protosw(&sctp_stream_protosw);
/* Allocate a cache pools. */
sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
sizeof(struct sctp_bind_bucket),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
if (!sctp_bucket_cachep)
goto err_bucket_cachep;
sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
sizeof(struct sctp_chunk),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
if (!sctp_chunk_cachep)
goto err_chunk_cachep;
/* Allocate and initialise sctp mibs. */ /* Allocate and initialise sctp mibs. */
status = init_sctp_mibs(); status = init_sctp_mibs();
if (status) if (status)
...@@ -982,8 +1003,8 @@ __init int sctp_init(void) ...@@ -982,8 +1003,8 @@ __init int sctp_init(void)
/* Allocate and initialize the association hash table. */ /* Allocate and initialize the association hash table. */
sctp_proto.assoc_hashsize = 4096; sctp_proto.assoc_hashsize = 4096;
sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *) sctp_proto.assoc_hashbucket = (struct sctp_hashbucket *)
kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_proto.assoc_hashbucket) { if (!sctp_proto.assoc_hashbucket) {
printk(KERN_ERR "SCTP: Failed association hash alloc.\n"); printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
status = -ENOMEM; status = -ENOMEM;
...@@ -996,8 +1017,8 @@ __init int sctp_init(void) ...@@ -996,8 +1017,8 @@ __init int sctp_init(void)
/* Allocate and initialize the endpoint hash table. */ /* Allocate and initialize the endpoint hash table. */
sctp_proto.ep_hashsize = 64; sctp_proto.ep_hashsize = 64;
sctp_proto.ep_hashbucket = (sctp_hashbucket_t *) sctp_proto.ep_hashbucket = (struct sctp_hashbucket *)
kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_proto.ep_hashbucket) { if (!sctp_proto.ep_hashbucket) {
printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
status = -ENOMEM; status = -ENOMEM;
...@@ -1011,8 +1032,8 @@ __init int sctp_init(void) ...@@ -1011,8 +1032,8 @@ __init int sctp_init(void)
/* Allocate and initialize the SCTP port hash table. */ /* Allocate and initialize the SCTP port hash table. */
sctp_proto.port_hashsize = 4096; sctp_proto.port_hashsize = 4096;
sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *) sctp_proto.port_hashtable = (struct sctp_bind_hashbucket *)
kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(struct sctp_bind_hashbucket),GFP_KERNEL);
if (!sctp_proto.port_hashtable) { if (!sctp_proto.port_hashtable) {
printk(KERN_ERR "SCTP: Failed bind hash alloc."); printk(KERN_ERR "SCTP: Failed bind hash alloc.");
status = -ENOMEM; status = -ENOMEM;
...@@ -1069,6 +1090,10 @@ __init int sctp_init(void) ...@@ -1069,6 +1090,10 @@ __init int sctp_init(void)
sctp_proc_exit(); sctp_proc_exit();
cleanup_sctp_mibs(); cleanup_sctp_mibs();
err_init_mibs: err_init_mibs:
kmem_cache_destroy(sctp_chunk_cachep);
err_chunk_cachep:
kmem_cache_destroy(sctp_bucket_cachep);
err_bucket_cachep:
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_seqpacket_protosw);
inet_unregister_protosw(&sctp_stream_protosw); inet_unregister_protosw(&sctp_stream_protosw);
...@@ -1099,6 +1124,9 @@ __exit void sctp_exit(void) ...@@ -1099,6 +1124,9 @@ __exit void sctp_exit(void)
kfree(sctp_proto.ep_hashbucket); kfree(sctp_proto.ep_hashbucket);
kfree(sctp_proto.port_hashtable); kfree(sctp_proto.port_hashtable);
kmem_cache_destroy(sctp_chunk_cachep);
kmem_cache_destroy(sctp_bucket_cachep);
sctp_dbg_objcnt_exit(); sctp_dbg_objcnt_exit();
sctp_proc_exit(); sctp_proc_exit();
cleanup_sctp_mibs(); cleanup_sctp_mibs();
......
...@@ -68,6 +68,8 @@ ...@@ -68,6 +68,8 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
extern kmem_cache_t *sctp_chunk_cachep;
/* What was the inbound interface for this chunk? */ /* What was the inbound interface for this chunk? */
int sctp_chunk_iif(const struct sctp_chunk *chunk) int sctp_chunk_iif(const struct sctp_chunk *chunk)
{ {
...@@ -976,7 +978,9 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, ...@@ -976,7 +978,9 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
const struct sctp_association *asoc, const struct sctp_association *asoc,
struct sock *sk) struct sock *sk)
{ {
struct sctp_chunk *retval = t_new(struct sctp_chunk, GFP_ATOMIC); struct sctp_chunk *retval;
retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC);
if (!retval) if (!retval)
goto nodata; goto nodata;
...@@ -1075,13 +1079,12 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, ...@@ -1075,13 +1079,12 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
} }
retval->chunk_hdr = chunk_hdr; retval->chunk_hdr = chunk_hdr;
retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(sctp_chunkhdr_t); retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);
/* Set the skb to the belonging sock for accounting. */ /* Set the skb to the belonging sock for accounting. */
skb->sk = sk; skb->sk = sk;
return retval; return retval;
nodata: nodata:
return NULL; return NULL;
} }
...@@ -1090,12 +1093,11 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, ...@@ -1090,12 +1093,11 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
/* Release the memory occupied by a chunk. */ /* Release the memory occupied by a chunk. */
static void sctp_chunk_destroy(struct sctp_chunk *chunk) static void sctp_chunk_destroy(struct sctp_chunk *chunk)
{ {
/* Free the chunk skb data and the SCTP_chunk stub itself. */ /* Free the chunk skb data and the SCTP_chunk stub itself. */
dev_kfree_skb(chunk->skb); dev_kfree_skb(chunk->skb);
kfree(chunk);
SCTP_DBG_OBJCNT_DEC(chunk); SCTP_DBG_OBJCNT_DEC(chunk);
kmem_cache_free(sctp_chunk_cachep, chunk);
} }
/* Possibly, free the chunk. */ /* Possibly, free the chunk. */
......
...@@ -99,6 +99,8 @@ static void sctp_sock_migrate(struct sock *, struct sock *, ...@@ -99,6 +99,8 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
struct sctp_association *, sctp_socket_type_t); struct sctp_association *, sctp_socket_type_t);
static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
extern kmem_cache_t *sctp_bucket_cachep;
/* Look up the association by its id. If this is not a UDP-style /* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored. * socket, the ID field is always ignored.
*/ */
...@@ -2721,7 +2723,7 @@ static void sctp_unhash(struct sock *sk) ...@@ -2721,7 +2723,7 @@ static void sctp_unhash(struct sock *sk)
* *
* The port hash table (contained in the 'global' SCTP protocol storage * The port hash table (contained in the 'global' SCTP protocol storage
* returned by struct sctp_protocol *sctp_get_protocol()). The hash * returned by struct sctp_protocol *sctp_get_protocol()). The hash
* table is an array of 4096 lists (sctp_bind_hashbucket_t). Each * table is an array of 4096 lists (sctp_bind_hashbucket). Each
* list (the list number is the port number hashed out, so as you * list (the list number is the port number hashed out, so as you
* would expect from a hash function, all the ports in a given list have * would expect from a hash function, all the ports in a given list have
* such a number that hashes out to the same list number; you were * such a number that hashes out to the same list number; you were
...@@ -2729,12 +2731,13 @@ static void sctp_unhash(struct sock *sk) ...@@ -2729,12 +2731,13 @@ static void sctp_unhash(struct sock *sk)
* link to the socket (struct sock) that uses it, the port number and * link to the socket (struct sock) that uses it, the port number and
* a fastreuse flag (FIXME: NPI ipg). * a fastreuse flag (FIXME: NPI ipg).
*/ */
static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, static struct sctp_bind_bucket *sctp_bucket_create(
unsigned short snum); struct sctp_bind_hashbucket *head, unsigned short snum);
static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{ {
sctp_bind_hashbucket_t *head; /* hash list */ struct sctp_bind_hashbucket *head; /* hash list */
sctp_bind_bucket_t *pp; /* hash list port iterator */ struct sctp_bind_bucket *pp; /* hash list port iterator */
struct sctp_protocol *sctp = sctp_get_protocol(); struct sctp_protocol *sctp = sctp_get_protocol();
unsigned short snum; unsigned short snum;
int ret; int ret;
...@@ -3105,12 +3108,12 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) ...@@ -3105,12 +3108,12 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
* 2nd Level Abstractions * 2nd Level Abstractions
********************************************************************/ ********************************************************************/
static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsigned short snum) static struct sctp_bind_bucket *sctp_bucket_create(
struct sctp_bind_hashbucket *head, unsigned short snum)
{ {
sctp_bind_bucket_t *pp; struct sctp_bind_bucket *pp;
SCTP_DEBUG_PRINTK( "sctp_bucket_create() begins, snum=%d\n", snum); pp = kmem_cache_alloc(sctp_bucket_cachep, SLAB_ATOMIC);
pp = kmalloc(sizeof(sctp_bind_bucket_t), GFP_ATOMIC);
if (pp) { if (pp) {
pp->port = snum; pp->port = snum;
pp->fastreuse = 0; pp->fastreuse = 0;
...@@ -3120,31 +3123,36 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi ...@@ -3120,31 +3123,36 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
head->chain = pp; head->chain = pp;
pp->pprev = &head->chain; pp->pprev = &head->chain;
} }
SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp);
return pp; return pp;
} }
/* Caller must hold hashbucket lock for this tb with local BH disabled */
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
if (pp->sk) {
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
kmem_cache_free(sctp_bucket_cachep, pp);
}
}
/* FIXME: Commments! */ /* FIXME: Commments! */
static __inline__ void __sctp_put_port(struct sock *sk) static __inline__ void __sctp_put_port(struct sock *sk)
{ {
struct sctp_protocol *sctp_proto = sctp_get_protocol(); struct sctp_protocol *sctp_proto = sctp_get_protocol();
sctp_bind_hashbucket_t *head = struct sctp_bind_hashbucket *head =
&sctp_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)]; &sctp_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
sctp_bind_bucket_t *pp; struct sctp_bind_bucket *pp;
sctp_spin_lock(&head->lock); sctp_spin_lock(&head->lock);
pp = (sctp_bind_bucket_t *) sk->prev; pp = (struct sctp_bind_bucket *) sk->prev;
if (sk->bind_next) if (sk->bind_next)
sk->bind_next->bind_pprev = sk->bind_pprev; sk->bind_next->bind_pprev = sk->bind_pprev;
*(sk->bind_pprev) = sk->bind_next; *(sk->bind_pprev) = sk->bind_next;
sk->prev = NULL; sk->prev = NULL;
inet_sk(sk)->num = 0; inet_sk(sk)->num = 0;
if (pp->sk) { sctp_bucket_destroy(pp);
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
kfree(pp);
}
sctp_spin_unlock(&head->lock); sctp_spin_unlock(&head->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