diff options
author | Len Brown <len.brown@intel.com> | 2005-09-03 02:44:09 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-09-03 02:44:09 -0400 |
commit | 129521dcc94f781890f8f668219ab79f0073ff9f (patch) | |
tree | 9f70707c88da65577f38814fe37b24c4b4957d64 /net/core/sock.c | |
parent | 824b558bbe2c298b165cdb54c33718994dda30bb (diff) | |
parent | f505380ba7b98ec97bf25300c2a58aeae903530b (diff) |
Merge linux-2.6 into linux-acpi-2.6 test
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 133 |
1 files changed, 125 insertions, 8 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 12f6d9a2a522..ccd10fd65682 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -260,7 +260,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
260 | 260 | ||
261 | if (val > sysctl_wmem_max) | 261 | if (val > sysctl_wmem_max) |
262 | val = sysctl_wmem_max; | 262 | val = sysctl_wmem_max; |
263 | 263 | set_sndbuf: | |
264 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; | 264 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; |
265 | if ((val * 2) < SOCK_MIN_SNDBUF) | 265 | if ((val * 2) < SOCK_MIN_SNDBUF) |
266 | sk->sk_sndbuf = SOCK_MIN_SNDBUF; | 266 | sk->sk_sndbuf = SOCK_MIN_SNDBUF; |
@@ -274,6 +274,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
274 | sk->sk_write_space(sk); | 274 | sk->sk_write_space(sk); |
275 | break; | 275 | break; |
276 | 276 | ||
277 | case SO_SNDBUFFORCE: | ||
278 | if (!capable(CAP_NET_ADMIN)) { | ||
279 | ret = -EPERM; | ||
280 | break; | ||
281 | } | ||
282 | goto set_sndbuf; | ||
283 | |||
277 | case SO_RCVBUF: | 284 | case SO_RCVBUF: |
278 | /* Don't error on this BSD doesn't and if you think | 285 | /* Don't error on this BSD doesn't and if you think |
279 | about it this is right. Otherwise apps have to | 286 | about it this is right. Otherwise apps have to |
@@ -282,7 +289,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
282 | 289 | ||
283 | if (val > sysctl_rmem_max) | 290 | if (val > sysctl_rmem_max) |
284 | val = sysctl_rmem_max; | 291 | val = sysctl_rmem_max; |
285 | 292 | set_rcvbuf: | |
286 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; | 293 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; |
287 | /* FIXME: is this lower bound the right one? */ | 294 | /* FIXME: is this lower bound the right one? */ |
288 | if ((val * 2) < SOCK_MIN_RCVBUF) | 295 | if ((val * 2) < SOCK_MIN_RCVBUF) |
@@ -291,6 +298,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
291 | sk->sk_rcvbuf = val * 2; | 298 | sk->sk_rcvbuf = val * 2; |
292 | break; | 299 | break; |
293 | 300 | ||
301 | case SO_RCVBUFFORCE: | ||
302 | if (!capable(CAP_NET_ADMIN)) { | ||
303 | ret = -EPERM; | ||
304 | break; | ||
305 | } | ||
306 | goto set_rcvbuf; | ||
307 | |||
294 | case SO_KEEPALIVE: | 308 | case SO_KEEPALIVE: |
295 | #ifdef CONFIG_INET | 309 | #ifdef CONFIG_INET |
296 | if (sk->sk_protocol == IPPROTO_TCP) | 310 | if (sk->sk_protocol == IPPROTO_TCP) |
@@ -686,6 +700,80 @@ void sk_free(struct sock *sk) | |||
686 | module_put(owner); | 700 | module_put(owner); |
687 | } | 701 | } |
688 | 702 | ||
703 | struct sock *sk_clone(const struct sock *sk, const unsigned int __nocast priority) | ||
704 | { | ||
705 | struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0); | ||
706 | |||
707 | if (newsk != NULL) { | ||
708 | struct sk_filter *filter; | ||
709 | |||
710 | memcpy(newsk, sk, sk->sk_prot->obj_size); | ||
711 | |||
712 | /* SANITY */ | ||
713 | sk_node_init(&newsk->sk_node); | ||
714 | sock_lock_init(newsk); | ||
715 | bh_lock_sock(newsk); | ||
716 | |||
717 | atomic_set(&newsk->sk_rmem_alloc, 0); | ||
718 | atomic_set(&newsk->sk_wmem_alloc, 0); | ||
719 | atomic_set(&newsk->sk_omem_alloc, 0); | ||
720 | skb_queue_head_init(&newsk->sk_receive_queue); | ||
721 | skb_queue_head_init(&newsk->sk_write_queue); | ||
722 | |||
723 | rwlock_init(&newsk->sk_dst_lock); | ||
724 | rwlock_init(&newsk->sk_callback_lock); | ||
725 | |||
726 | newsk->sk_dst_cache = NULL; | ||
727 | newsk->sk_wmem_queued = 0; | ||
728 | newsk->sk_forward_alloc = 0; | ||
729 | newsk->sk_send_head = NULL; | ||
730 | newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; | ||
731 | newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; | ||
732 | |||
733 | sock_reset_flag(newsk, SOCK_DONE); | ||
734 | skb_queue_head_init(&newsk->sk_error_queue); | ||
735 | |||
736 | filter = newsk->sk_filter; | ||
737 | if (filter != NULL) | ||
738 | sk_filter_charge(newsk, filter); | ||
739 | |||
740 | if (unlikely(xfrm_sk_clone_policy(newsk))) { | ||
741 | /* It is still raw copy of parent, so invalidate | ||
742 | * destructor and make plain sk_free() */ | ||
743 | newsk->sk_destruct = NULL; | ||
744 | sk_free(newsk); | ||
745 | newsk = NULL; | ||
746 | goto out; | ||
747 | } | ||
748 | |||
749 | newsk->sk_err = 0; | ||
750 | newsk->sk_priority = 0; | ||
751 | atomic_set(&newsk->sk_refcnt, 2); | ||
752 | |||
753 | /* | ||
754 | * Increment the counter in the same struct proto as the master | ||
755 | * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that | ||
756 | * is the same as sk->sk_prot->socks, as this field was copied | ||
757 | * with memcpy). | ||
758 | * | ||
759 | * This _changes_ the previous behaviour, where | ||
760 | * tcp_create_openreq_child always was incrementing the | ||
761 | * equivalent to tcp_prot->socks (inet_sock_nr), so this have | ||
762 | * to be taken into account in all callers. -acme | ||
763 | */ | ||
764 | sk_refcnt_debug_inc(newsk); | ||
765 | newsk->sk_socket = NULL; | ||
766 | newsk->sk_sleep = NULL; | ||
767 | |||
768 | if (newsk->sk_prot->sockets_allocated) | ||
769 | atomic_inc(newsk->sk_prot->sockets_allocated); | ||
770 | } | ||
771 | out: | ||
772 | return newsk; | ||
773 | } | ||
774 | |||
775 | EXPORT_SYMBOL_GPL(sk_clone); | ||
776 | |||
689 | void __init sk_init(void) | 777 | void __init sk_init(void) |
690 | { | 778 | { |
691 | if (num_physpages <= 4096) { | 779 | if (num_physpages <= 4096) { |
@@ -1353,11 +1441,7 @@ void sk_common_release(struct sock *sk) | |||
1353 | 1441 | ||
1354 | xfrm_sk_free_policy(sk); | 1442 | xfrm_sk_free_policy(sk); |
1355 | 1443 | ||
1356 | #ifdef INET_REFCNT_DEBUG | 1444 | sk_refcnt_debug_release(sk); |
1357 | if (atomic_read(&sk->sk_refcnt) != 1) | ||
1358 | printk(KERN_DEBUG "Destruction of the socket %p delayed, c=%d\n", | ||
1359 | sk, atomic_read(&sk->sk_refcnt)); | ||
1360 | #endif | ||
1361 | sock_put(sk); | 1445 | sock_put(sk); |
1362 | } | 1446 | } |
1363 | 1447 | ||
@@ -1368,7 +1452,8 @@ static LIST_HEAD(proto_list); | |||
1368 | 1452 | ||
1369 | int proto_register(struct proto *prot, int alloc_slab) | 1453 | int proto_register(struct proto *prot, int alloc_slab) |
1370 | { | 1454 | { |
1371 | char *request_sock_slab_name; | 1455 | char *request_sock_slab_name = NULL; |
1456 | char *timewait_sock_slab_name; | ||
1372 | int rc = -ENOBUFS; | 1457 | int rc = -ENOBUFS; |
1373 | 1458 | ||
1374 | if (alloc_slab) { | 1459 | if (alloc_slab) { |
@@ -1399,6 +1484,23 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
1399 | goto out_free_request_sock_slab_name; | 1484 | goto out_free_request_sock_slab_name; |
1400 | } | 1485 | } |
1401 | } | 1486 | } |
1487 | |||
1488 | if (prot->twsk_obj_size) { | ||
1489 | static const char mask[] = "tw_sock_%s"; | ||
1490 | |||
1491 | timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); | ||
1492 | |||
1493 | if (timewait_sock_slab_name == NULL) | ||
1494 | goto out_free_request_sock_slab; | ||
1495 | |||
1496 | sprintf(timewait_sock_slab_name, mask, prot->name); | ||
1497 | prot->twsk_slab = kmem_cache_create(timewait_sock_slab_name, | ||
1498 | prot->twsk_obj_size, | ||
1499 | 0, SLAB_HWCACHE_ALIGN, | ||
1500 | NULL, NULL); | ||
1501 | if (prot->twsk_slab == NULL) | ||
1502 | goto out_free_timewait_sock_slab_name; | ||
1503 | } | ||
1402 | } | 1504 | } |
1403 | 1505 | ||
1404 | write_lock(&proto_list_lock); | 1506 | write_lock(&proto_list_lock); |
@@ -1407,6 +1509,13 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
1407 | rc = 0; | 1509 | rc = 0; |
1408 | out: | 1510 | out: |
1409 | return rc; | 1511 | return rc; |
1512 | out_free_timewait_sock_slab_name: | ||
1513 | kfree(timewait_sock_slab_name); | ||
1514 | out_free_request_sock_slab: | ||
1515 | if (prot->rsk_prot && prot->rsk_prot->slab) { | ||
1516 | kmem_cache_destroy(prot->rsk_prot->slab); | ||
1517 | prot->rsk_prot->slab = NULL; | ||
1518 | } | ||
1410 | out_free_request_sock_slab_name: | 1519 | out_free_request_sock_slab_name: |
1411 | kfree(request_sock_slab_name); | 1520 | kfree(request_sock_slab_name); |
1412 | out_free_sock_slab: | 1521 | out_free_sock_slab: |
@@ -1434,6 +1543,14 @@ void proto_unregister(struct proto *prot) | |||
1434 | prot->rsk_prot->slab = NULL; | 1543 | prot->rsk_prot->slab = NULL; |
1435 | } | 1544 | } |
1436 | 1545 | ||
1546 | if (prot->twsk_slab != NULL) { | ||
1547 | const char *name = kmem_cache_name(prot->twsk_slab); | ||
1548 | |||
1549 | kmem_cache_destroy(prot->twsk_slab); | ||
1550 | kfree(name); | ||
1551 | prot->twsk_slab = NULL; | ||
1552 | } | ||
1553 | |||
1437 | list_del(&prot->node); | 1554 | list_del(&prot->node); |
1438 | write_unlock(&proto_list_lock); | 1555 | write_unlock(&proto_list_lock); |
1439 | } | 1556 | } |