diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 23:09:30 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:42:13 -0400 |
commit | 8feaf0c0a5488b3d898a9c207eb6678f44ba3f26 (patch) | |
tree | ddd004afe2f7c8295f6fdb94d34f78a42b5961cb /net/core | |
parent | 33b62231908c58ae04185e4f1063d1e35a7c8576 (diff) |
[INET]: Generalise tcp_tw_bucket, aka TIME_WAIT sockets
This paves the way to generalise the rest of the sock ID lookup
routines and saves some bytes in TCPv4 TIME_WAIT sockets on distro
kernels (where IPv6 is always built as a module):
[root@qemu ~]# grep tw_sock /proc/slabinfo
tw_sock_TCPv6 0 0 128 31 1
tw_sock_TCP 0 0 96 41 1
[root@qemu ~]#
Now if a protocol wants to use the TIME_WAIT generic infrastructure it
only has to set the sk_prot->twsk_obj_size field with the size of its
inet_timewait_sock derived sock and proto_register will create
sk_prot->twsk_slab, for now its only for INET sockets, but we can
introduce timewait_sock later if some non INET transport protocolo
wants to use this stuff.
Next changesets will take advantage of this new infrastructure to
generalise even more TCP code.
[acme@toy net-2.6.14]$ grep built-in /tmp/before.size /tmp/after.size
/tmp/before.size: 188646 11764 5068 205478 322a6 net/ipv4/built-in.o
/tmp/after.size: 188144 11764 5068 204976 320b0 net/ipv4/built-in.o
[acme@toy net-2.6.14]$
Tested with both IPv4 & IPv6 (::1 (localhost) & ::ffff:172.20.0.1
(qemu host)).
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/sock.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index a1a23be10aa3..aba31fedf2ac 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1378,7 +1378,8 @@ static LIST_HEAD(proto_list); | |||
1378 | 1378 | ||
1379 | int proto_register(struct proto *prot, int alloc_slab) | 1379 | int proto_register(struct proto *prot, int alloc_slab) |
1380 | { | 1380 | { |
1381 | char *request_sock_slab_name; | 1381 | char *request_sock_slab_name = NULL; |
1382 | char *timewait_sock_slab_name; | ||
1382 | int rc = -ENOBUFS; | 1383 | int rc = -ENOBUFS; |
1383 | 1384 | ||
1384 | if (alloc_slab) { | 1385 | if (alloc_slab) { |
@@ -1409,6 +1410,23 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
1409 | goto out_free_request_sock_slab_name; | 1410 | goto out_free_request_sock_slab_name; |
1410 | } | 1411 | } |
1411 | } | 1412 | } |
1413 | |||
1414 | if (prot->twsk_obj_size) { | ||
1415 | static const char mask[] = "tw_sock_%s"; | ||
1416 | |||
1417 | timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); | ||
1418 | |||
1419 | if (timewait_sock_slab_name == NULL) | ||
1420 | goto out_free_request_sock_slab; | ||
1421 | |||
1422 | sprintf(timewait_sock_slab_name, mask, prot->name); | ||
1423 | prot->twsk_slab = kmem_cache_create(timewait_sock_slab_name, | ||
1424 | prot->twsk_obj_size, | ||
1425 | 0, SLAB_HWCACHE_ALIGN, | ||
1426 | NULL, NULL); | ||
1427 | if (prot->twsk_slab == NULL) | ||
1428 | goto out_free_timewait_sock_slab_name; | ||
1429 | } | ||
1412 | } | 1430 | } |
1413 | 1431 | ||
1414 | write_lock(&proto_list_lock); | 1432 | write_lock(&proto_list_lock); |
@@ -1417,6 +1435,13 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
1417 | rc = 0; | 1435 | rc = 0; |
1418 | out: | 1436 | out: |
1419 | return rc; | 1437 | return rc; |
1438 | out_free_timewait_sock_slab_name: | ||
1439 | kfree(timewait_sock_slab_name); | ||
1440 | out_free_request_sock_slab: | ||
1441 | if (prot->rsk_prot && prot->rsk_prot->slab) { | ||
1442 | kmem_cache_destroy(prot->rsk_prot->slab); | ||
1443 | prot->rsk_prot->slab = NULL; | ||
1444 | } | ||
1420 | out_free_request_sock_slab_name: | 1445 | out_free_request_sock_slab_name: |
1421 | kfree(request_sock_slab_name); | 1446 | kfree(request_sock_slab_name); |
1422 | out_free_sock_slab: | 1447 | out_free_sock_slab: |
@@ -1444,6 +1469,14 @@ void proto_unregister(struct proto *prot) | |||
1444 | prot->rsk_prot->slab = NULL; | 1469 | prot->rsk_prot->slab = NULL; |
1445 | } | 1470 | } |
1446 | 1471 | ||
1472 | if (prot->twsk_slab != NULL) { | ||
1473 | const char *name = kmem_cache_name(prot->twsk_slab); | ||
1474 | |||
1475 | kmem_cache_destroy(prot->twsk_slab); | ||
1476 | kfree(name); | ||
1477 | prot->twsk_slab = NULL; | ||
1478 | } | ||
1479 | |||
1447 | list_del(&prot->node); | 1480 | list_del(&prot->node); |
1448 | write_unlock(&proto_list_lock); | 1481 | write_unlock(&proto_list_lock); |
1449 | } | 1482 | } |