generalise per socket slab cache use
Subsystems (6)
PATCH 1/1 generalise per socket slab cache use
Hi,
Please see if it is acceptable, if it is, please pull from:
bk://kernel.bkbits.net/acme/net-2.6
I want to improve it a bit by not passing the slab cache name tosk_alloc_slab, but create the name from the sk->sk_prot->name member, but unfortunately the kmem_cache_t struct stores a pointer to the slab cache name, which also creates problems for other improvements, like my __initstr patch, that moves the strings in __init and __exit functions to .text.init and .text.exit, perhaps I should send a patch to the slab code to have a char array to store the slab cache name.
Comments?
Best Regards,
- Arnaldo
You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.
===================================================================
[email protected], 2004-09-11 00:02:02-03:00, [email protected]
[NET] generalise per socket slab cache use
With this patch we get two new slabcaches, for sctp socks, that previously were being allocated on the default, that was tcp[6]_sock, i.e. wasting 288 bytes per sock in the IPv4 case and 256 bytes for the IPv6 version, this is in preparation for DCCP (or any other new protocol :) ).
With this in place another nice side effect that is easier to achieve is to get rid of struct sock sk->sk_slab, and instead use sk->sk_prot->slab, saving sizeof(void *) on every struct sock instance, but this unfortunatly has to wait for the conversion of all protocols that use per socket slabcaches to use sk->sk_prot, AF_UNIX is the only one AFAIK, so I'll try to convert it to use sk->sk_prot and then get rid of sk->sk_slab.
As for the protocols that don't use per socket slabcaches its just a matter of defaulting to sk_cachep at sk_free time if sk->sk_prot is NULL.
[root@qemu ~]# modprobe sctp
[root@qemu ~]# grep _sock /proc/slabinfo
sctpv6_sock 9 9 864 9 2 : tunables 54 27 0 : sctp_sock 0 0 736 5 1 : tunables 54 27 0 : rawv6_sock 3 6 640 6 1 : tunables 54 27 0 : udpv6_sock 0 0 608 6 1 : tunables 54 27 0 : tcpv6_sock 1 7 1120 7 2 : tunables 24 12 0 : unix_sock 6 10 384 10 1 : tunables 54 27 0 : raw_sock 2 8 480 8 1 : tunables 54 27 0 : udp_sock 0 0 512 7 1 : tunables 54 27 0 : tcp_sock 0 0 1024 4 1 : tunables 54 27 0 :
include/linux/ipv6.h | 4 + include/net/raw.h | 1 include/net/sctp/sctp.h | 1 include/net/sock.h | 7 ++ include/net/tcp.h | 3 net/core/sock.c | 21 ++++++ net/ipv4/af_inet.c | 103 ++++++++++++++------------------ net/ipv4/raw.c | 1 net/ipv4/tcp_ipv4.c | 1 net/ipv4/tcp_minisocks.c | 2 net/ipv4/udp.c | 1 net/ipv6/af_inet6.c | 151 +++++++++++++++++++---------------------------- net/ipv6/raw.c | 6 + net/ipv6/tcp_ipv6.c | 6 + net/ipv6/udp.c | 6 + net/sctp/ipv6.c | 24 +++++-- net/sctp/protocol.c | 26 +++++--- net/sctp/socket.c | 30 +++++++++ 18 files changed, 231 insertions(+), 163 deletions(-)
include/linux/ipv6.h +4 -0
@@ -282,6 +282,10 @@return &((struct raw6_sock *)__sk)->raw6; } +struct ipv6_sk_offset { +int offset; +}; +#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE )#define __ipv6_only_sock (sk) (inet6_sk(sk)->ipv6only)#define ipv6_only_sock (sk) ((sk)->sk_family == PF_INET6 && __ipv6_only_sock(sk))
include/net/raw.h +0 -1
@@ -17,7 +17,6 @@#ifndef _RAW_H#define _RAW_H -extern struct proto raw_prot;
include/net/sctp/sctp.h +1 -0
@@ -505,6 +505,7 @@/* External references. */ extern struct proto sctp_prot; +extern struct proto sctpv6_prot;extern struct proc_dir_entry *proc_net_sctp;void sctp_put_port (struct sock *sk);
include/net/sock.h +7 -0
@@ -410,6 +410,9 @@return test_bit (flag, &sk->sk_flags); } +extern int sk_alloc_slab (struct proto *prot,char *name); +extern void sk_free_slab (struct proto *prot); +static inline void sk_acceptq_removed (struct sock *sk) { sk->sk_ack_backlog--;
@@ -554,6 +557,10 @@int *sysctl_wmem;int *sysctl_rmem;int max_header; + +kmem_cache_t *slab; +int slab_obj_size; +void *af_specific;char name[32 ];
include/net/tcp.h +0 -3
@@ -153,9 +153,6 @@#define tcp_lhash_wait (tcp_hashinfo.__tcp_lhash_wait)#define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock) -/* SLAB cache for TCP socks */ -extern kmem_cache_t *tcp_sk_cachep; -extern kmem_cache_t *tcp_bucket_cachep;extern struct tcp_bind_bucket *tcp_bucket_create (struct tcp_bind_hashbucket *head,unsigned short snum);
net/core/sock.c +21 -0
@@ -1343,6 +1343,27 @@EXPORT_SYMBOL (sk_common_release); +int sk_alloc_slab (struct proto *prot,char *name) +{ + prot->slab =kmem_cache_create (name, + prot->slab_obj_size,0 , +SLAB_HWCACHE_ALIGN ,NULL ,NULL ); + +return prot->slab !=NULL ?0 : -ENOBUFS ; +} + +EXPORT_SYMBOL (sk_alloc_slab); + +void sk_free_slab (struct proto *prot) +{ +if (prot->slab !=NULL ) { +kmem_cache_destroy (prot->slab); + prot->slab =NULL ; + } +} + +EXPORT_SYMBOL (sk_free_slab); +EXPORT_SYMBOL (__lock_sock);EXPORT_SYMBOL (__release_sock);EXPORT_SYMBOL (sk_alloc);
net/ipv4/af_inet.c +47 -56
160 lines not on this page · raw message
net/ipv4/raw.c +1 -0
@@ -719,6 +719,7 @@ .backlog_rcv = raw_rcv_skb, .hash = raw_v4_hash, .unhash = raw_v4_unhash, + .slab_obj_size = sizeof(struct raw_sock), };#ifdef CONFIG_PROC_FS
net/ipv4/tcp_ipv4.c +1 -0
@@ -2617,6 +2617,7 @@ .sysctl_wmem = sysctl_tcp_wmem, .sysctl_rmem = sysctl_tcp_rmem, .max_header = MAX_TCP_HEADER, + .slab_obj_size = sizeof(struct tcp_sock), };
net/ipv4/tcp_minisocks.c +1 -1
@@ -687,7 +687,7 @@/* allocate the newsk from the same slab of the master sock, * if not, at sk_free time we'll try to free it from the wrong * slabcache (i.e. is it TCPv4 or v6?) -acme */ -struct sock *newsk =sk_alloc (PF_INET ,GFP_ATOMIC ,0 , sk->sk_slab); +struct sock *newsk =sk_alloc (PF_INET ,GFP_ATOMIC ,0 , sk->sk_prot->slab);if (newsk !=NULL ) {struct tcp_opt *newtp;
net/ipv4/udp.c +1 -0
@@ -1320,6 +1320,7 @@ .hash = udp_v4_hash, .unhash = udp_v4_unhash, .get_port = udp_v4_get_port, + .slab_obj_size = sizeof(struct udp_sock), };/* ------------------------------------------------------------------------ */
net/ipv6/af_inet6.c +64 -87
229 lines not on this page · raw message
net/ipv6/raw.c +6 -0
@@ -973,6 +973,10 @@return (0 ); } +struct ipv6_sk_offset raw_sock_offset = { + .offset = offsetof(struct udp6_sock , inet6), +}; +struct proto rawv6_prot = { .name ="RAW" , .close = rawv6_close,
@@ -989,6 +993,8 @@ .backlog_rcv = rawv6_rcv_skb, .hash = raw_v6_hash, .unhash = raw_v6_unhash, + .slab_obj_size = sizeof(struct raw6_sock), + .af_specific = &raw_sock_offset, };#ifdef CONFIG_PROC_FS
net/ipv6/tcp_ipv6.c +6 -0
@@ -2119,6 +2119,10 @@ }#endif +struct ipv6_sk_offset tcp_sock_offset = { + .offset = offsetof(struct tcp6_sock , inet6), +}; +struct proto tcpv6_prot = { .name ="TCPv6" , .close = tcp_close,
@@ -2145,6 +2149,8 @@ .sysctl_wmem = sysctl_tcp_wmem, .sysctl_rmem = sysctl_tcp_rmem, .max_header = MAX_TCP_HEADER, + .slab_obj_size = sizeof(struct tcp6_sock), + .af_specific = &tcp_sock_offset, };static struct inet6_protocol tcpv6_protocol = {
net/ipv6/udp.c +6 -0
@@ -1031,6 +1031,10 @@/* ------------------------------------------------------------------------ */ +struct ipv6_sk_offset udp_sock_offset = { + .offset = offsetof(struct udp6_sock , inet6), +}; +struct proto udpv6_prot = { .name ="UDP" , .close = udpv6_close,
@@ -1046,6 +1050,8 @@ .hash = udp_v6_hash, .unhash = udp_v6_unhash, .get_port = udp_v6_get_port, + .slab_obj_size = sizeof(struct udp6_sock), + .af_specific = &udp_sock_offset, };extern struct proto_ops inet6_dgram_ops;
net/sctp/ipv6.c +17 -7
@@ -583,8 +583,8 @@struct ipv6_pinfo *newnp, *np =inet6_sk (sk);struct sctp6_sock *newsctp6sk; - newsk =sk_alloc (PF_INET6 ,GFP_KERNEL ,sizeof (struct sctp6_sock ), - sk->sk_slab); + newsk =sk_alloc (PF_INET6 ,GFP_KERNEL , sk->sk_prot->slab_obj_size, + sk->sk_prot->slab);if (!newsk) goto out;
@@ -892,7 +892,7 @@static struct inet_protosw sctpv6_seqpacket_protosw = { .type =SOCK_SEQPACKET , .protocol =IPPROTO_SCTP , - .prot = &sctp_prot, + .prot = &sctpv6_prot, .ops = &inet6_seqpacket_ops, .capability =-1 , .no_check =0 ,
@@ -901,7 +901,7 @@static struct inet_protosw sctpv6_stream_protosw = { .type =SOCK_STREAM , .protocol =IPPROTO_SCTP , - .prot = &sctp_prot, + .prot = &sctpv6_prot, .ops = &inet6_seqpacket_ops, .capability =-1 , .no_check =0 ,
@@ -963,9 +963,14 @@/* Initialize IPv6 support and register with inet6 stack. */ int sctp_v6_init (void ) { +int rc =sk_alloc_slab (&sctpv6_prot,"sctpv6_sock" ); + +if (rc) + goto out;/* Register inet6 protocol. */ + rc = -EAGAIN ;if (inet6_add_protocol (&sctpv6_protocol,IPPROTO_SCTP ) <0 ) -return -EAGAIN ; + goto out_sctp_free_slab;/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */ inet6_register_protosw (&sctpv6_seqpacket_protosw);
@@ -979,8 +984,12 @@/* Register notifier for inet6 address additions/deletions. */ register_inet6addr_notifier (&sctp_inetaddr_notifier); - -return 0 ; + rc =0 ; +out: +return rc; +out_sctp_free_slab: +sk_free_slab (&sctpv6_prot); + goto out; }/* IPv6 specific exit support. */
@@ -991,4 +1000,5 @@inet6_unregister_protosw (&sctpv6_seqpacket_protosw);inet6_unregister_protosw (&sctpv6_stream_protosw);unregister_inet6addr_notifier (&sctp_inetaddr_notifier); +sk_free_slab (&sctpv6_prot); }
net/sctp/protocol.c +18 -8
@@ -554,8 +554,8 @@struct inet_opt *inet =inet_sk (sk);struct inet_opt *newinet; - newsk =sk_alloc (PF_INET ,GFP_KERNEL ,sizeof (struct sctp_sock ), - sk->sk_slab); + newsk =sk_alloc (PF_INET ,GFP_KERNEL , sk->sk_prot->slab_obj_size, + sk->sk_prot->slab);if (!newsk) goto out;
@@ -962,23 +962,29 @@__init int sctp_init (void ) {int i; -int status =0 ; +int status = -EINVAL ;unsigned long goal;int order;/* SCTP_DEBUG sanity check. */ if (!sctp_sanity_check ()) -return -EINVAL ; + goto out; + + status =sk_alloc_slab (&sctp_prot,"sctp_sock" ); +if (status) + goto out;/* Add SCTP to inet_protos hash table. */ + status = -EAGAIN ;if (inet_add_protocol (&sctp_protocol,IPPROTO_SCTP ) <0 ) -return -EAGAIN ; + goto err_add_protocol;/* Add SCTP(TCP and UDP style) to inetsw linked list. */ inet_register_protosw (&sctp_seqpacket_protosw);inet_register_protosw (&sctp_stream_protosw);/* Allocate a cache pools. */ + status = -ENOBUFS ; sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", sizeof(struct sctp_bind_bucket), 0, SLAB_HWCACHE_ALIGN,
@@ -1154,8 +1160,11 @@sctp_get_local_addr_list ();__unsafe (THIS_MODULE ); -return 0 ; - + status =0 ; +out: +return status; +err_add_protocol: +sk_free_slab (&sctp_prot); err_ctl_sock_init:sctp_v6_exit (); err_v6_init:
@@ -1183,7 +1192,7 @@inet_del_protocol (&sctp_protocol,IPPROTO_SCTP );inet_unregister_protosw (&sctp_seqpacket_protosw);inet_unregister_protosw (&sctp_stream_protosw); -return status; + goto out; }/* Exit handler for the SCTP protocol. */
@@ -1224,6 +1233,7 @@inet_del_protocol (&sctp_protocol,IPPROTO_SCTP );inet_unregister_protosw (&sctp_seqpacket_protosw);inet_unregister_protosw (&sctp_stream_protosw); +sk_free_slab (&sctp_prot); }module_init (sctp_init);
net/sctp/socket.c +30 -0
@@ -4622,4 +4622,34 @@ .hash = sctp_hash, .unhash = sctp_unhash, .get_port = sctp_get_port, + .slab_obj_size = sizeof(struct sctp_sock), }; + +#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE ) +struct ipv6_sk_offset sctp_sock_offset = { + .offset = offsetof(struct sctp6_sock , inet6), +}; + +struct proto sctpv6_prot = { + .name ="SCTPv6" , + .close = sctp_close, + .connect = sctp_connect, + .disconnect = sctp_disconnect, + .accept = sctp_accept, + .ioctl = sctp_ioctl, + .init = sctp_init_sock, + .destroy = sctp_destroy_sock, + .shutdown = sctp_shutdown, + .setsockopt = sctp_setsockopt, + .getsockopt = sctp_getsockopt, + .sendmsg = sctp_sendmsg, + .recvmsg = sctp_recvmsg, + .bind = sctp_bind, + .backlog_rcv = sctp_backlog_rcv, + .hash = sctp_hash, + .unhash = sctp_unhash, + .get_port = sctp_get_port, + .slab_obj_size =sizeof (struct sctp6_sock ), + .af_specific = &sctp_sock_offset, +}; +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
Arnaldo,
looks good, but i have a few comments. It is great that SCTP now has its own slabcaches.
net/ipv6/raw.c line 978
Quoted 3 lines
net/ipv6/raw.c +3
-0+struct ipv6_sk_offset raw_sock_offset = { + .offset = offsetof(struct udp6_sock , inet6), +};
I think there is a typo here. udp6_sock should be raw6_sock
net/ipv6/af_inet6.c line 729
Quoted 2 lines
net/ipv6/af_inet6.c +0
-2-printk (KERN_CRIT "%s: Can't create protocol sock SLAB " -"caches!\n" , __FUNCTION__);
You have removed the above critical messages. Is this by intent or a mistake.
I am not clear on why we need this new structure ipv6_sk_offset.
include/linux/ipv6.h line 288
Quoted 4 lines
include/linux/ipv6.h +4
-0+struct ipv6_sk_offset { +int offset; +}; +
Instead of adding the new field void *af_specific to struct proto, is it not sufficient to add
int pinet6_offset;
and assign it as follows for each v6 sock type
.pinet6_offset = offsetof(struct struct tcp6_sock, inet6)
In inet6_sk_generic(), you can directly use sk->sk_prot->pinet6_offset.
Thanks
Sridhar
Em Seg 13 Set 2004 18:17, Sridhar Samudrala escreveu:
Quoted 10 lines
Arnaldo,
looks good, but i have a few comments. It is great that SCTP now has its own slabcaches.
net/ipv6/raw.c line 978
Quoted 3 lines
net/ipv6/raw.c +3
-0+struct ipv6_sk_offset raw_sock_offset = { + .offset = offsetof(struct udp6_sock , inet6), +};I think there is a typo here.
udp6_sockshould beraw6_sock
Good spotting! I'll fix this one
Quoted 5 lines
net/ipv6/af_inet6.c line 729
Quoted 2 lines
net/ipv6/af_inet6.c +0
-2-printk (KERN_CRIT "%s: Can't create protocol sock SLAB " -"caches!\n" , __FUNCTION__);You have removed the above critical messages. Is this by intent or a mistake.
Humm, I'll put it on the sk_alloc_slab callers
Quoted 10 lines
I am not clear on why we need this new structure
ipv6_sk_offset.include/linux/ipv6.h line 288
Quoted 4 lines
include/linux/ipv6.h +4
-0+struct ipv6_sk_offset { +int offset; +}; +Instead of adding the new field void
*af_specificto struct proto, is it not sufficient to add
Quoted 6 lines
int pinet6_offset;and assign it as follows for each v6 sock type
.pinet6_offset =offsetof(struct struct tcp6_sock, inet6)In
inet6_sk_generic(), you can directly usesk->sk_prot->pinet6_offset.
I thought about it, but idea was to not introduce any family specific stuff in struct proto, I don't plan to have LLC over IPv6, for instance :)
Quoted 2 lines
Thanks
Sridhar
David S. Miller
maintainerQuoted 3 lines · On Mon, 13 Sep 2004 18:51:08 -0300 Arnaldo Carvalho de Melo…
Quoted 1 line
I think there is a typo here.
udp6_sockshould beraw6_sockGood spotting! I'll fix this one
Let me know when the fixed version is available, thanks. :)