aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1ce6b60b7f93..353284360751 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -82,6 +82,7 @@
82#include <asm/system.h> 82#include <asm/system.h>
83#include <asm/uaccess.h> 83#include <asm/uaccess.h>
84#include <asm/ioctls.h> 84#include <asm/ioctls.h>
85#include <linux/bootmem.h>
85#include <linux/types.h> 86#include <linux/types.h>
86#include <linux/fcntl.h> 87#include <linux/fcntl.h>
87#include <linux/module.h> 88#include <linux/module.h>
@@ -118,6 +119,17 @@ EXPORT_SYMBOL(udp_stats_in6);
118struct hlist_head udp_hash[UDP_HTABLE_SIZE]; 119struct hlist_head udp_hash[UDP_HTABLE_SIZE];
119DEFINE_RWLOCK(udp_hash_lock); 120DEFINE_RWLOCK(udp_hash_lock);
120 121
122int sysctl_udp_mem[3] __read_mostly;
123int sysctl_udp_rmem_min __read_mostly;
124int sysctl_udp_wmem_min __read_mostly;
125
126EXPORT_SYMBOL(sysctl_udp_mem);
127EXPORT_SYMBOL(sysctl_udp_rmem_min);
128EXPORT_SYMBOL(sysctl_udp_wmem_min);
129
130atomic_t udp_memory_allocated;
131EXPORT_SYMBOL(udp_memory_allocated);
132
121static inline int __udp_lib_lport_inuse(__u16 num, 133static inline int __udp_lib_lport_inuse(__u16 num,
122 const struct hlist_head udptable[]) 134 const struct hlist_head udptable[])
123{ 135{
@@ -901,13 +913,17 @@ try_again:
901 err = ulen; 913 err = ulen;
902 914
903out_free: 915out_free:
916 lock_sock(sk);
904 skb_free_datagram(sk, skb); 917 skb_free_datagram(sk, skb);
918 release_sock(sk);
905out: 919out:
906 return err; 920 return err;
907 921
908csum_copy_err: 922csum_copy_err:
923 lock_sock(sk);
909 if (!skb_kill_datagram(sk, skb, flags)) 924 if (!skb_kill_datagram(sk, skb, flags))
910 UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); 925 UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
926 release_sock(sk);
911 927
912 if (noblock) 928 if (noblock)
913 return -EAGAIN; 929 return -EAGAIN;
@@ -1072,7 +1088,15 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
1072 skb1 = skb_clone(skb, GFP_ATOMIC); 1088 skb1 = skb_clone(skb, GFP_ATOMIC);
1073 1089
1074 if (skb1) { 1090 if (skb1) {
1075 int ret = udp_queue_rcv_skb(sk, skb1); 1091 int ret = 0;
1092
1093 bh_lock_sock_nested(sk);
1094 if (!sock_owned_by_user(sk))
1095 ret = udp_queue_rcv_skb(sk, skb1);
1096 else
1097 sk_add_backlog(sk, skb1);
1098 bh_unlock_sock(sk);
1099
1076 if (ret > 0) 1100 if (ret > 0)
1077 /* we should probably re-process instead 1101 /* we should probably re-process instead
1078 * of dropping packets here. */ 1102 * of dropping packets here. */
@@ -1165,7 +1189,13 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1165 inet_iif(skb), udptable); 1189 inet_iif(skb), udptable);
1166 1190
1167 if (sk != NULL) { 1191 if (sk != NULL) {
1168 int ret = udp_queue_rcv_skb(sk, skb); 1192 int ret = 0;
1193 bh_lock_sock_nested(sk);
1194 if (!sock_owned_by_user(sk))
1195 ret = udp_queue_rcv_skb(sk, skb);
1196 else
1197 sk_add_backlog(sk, skb);
1198 bh_unlock_sock(sk);
1169 sock_put(sk); 1199 sock_put(sk);
1170 1200
1171 /* a return value > 0 means to resubmit the input, but 1201 /* a return value > 0 means to resubmit the input, but
@@ -1460,6 +1490,10 @@ struct proto udp_prot = {
1460 .hash = udp_lib_hash, 1490 .hash = udp_lib_hash,
1461 .unhash = udp_lib_unhash, 1491 .unhash = udp_lib_unhash,
1462 .get_port = udp_v4_get_port, 1492 .get_port = udp_v4_get_port,
1493 .memory_allocated = &udp_memory_allocated,
1494 .sysctl_mem = sysctl_udp_mem,
1495 .sysctl_wmem = &sysctl_udp_wmem_min,
1496 .sysctl_rmem = &sysctl_udp_rmem_min,
1463 .obj_size = sizeof(struct udp_sock), 1497 .obj_size = sizeof(struct udp_sock),
1464#ifdef CONFIG_COMPAT 1498#ifdef CONFIG_COMPAT
1465 .compat_setsockopt = compat_udp_setsockopt, 1499 .compat_setsockopt = compat_udp_setsockopt,
@@ -1655,6 +1689,25 @@ void udp4_proc_exit(void)
1655} 1689}
1656#endif /* CONFIG_PROC_FS */ 1690#endif /* CONFIG_PROC_FS */
1657 1691
1692void __init udp_init(void)
1693{
1694 unsigned long limit;
1695
1696 /* Set the pressure threshold up by the same strategy of TCP. It is a
1697 * fraction of global memory that is up to 1/2 at 256 MB, decreasing
1698 * toward zero with the amount of memory, with a floor of 128 pages.
1699 */
1700 limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
1701 limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
1702 limit = max(limit, 128UL);
1703 sysctl_udp_mem[0] = limit / 4 * 3;
1704 sysctl_udp_mem[1] = limit;
1705 sysctl_udp_mem[2] = sysctl_udp_mem[0] * 2;
1706
1707 sysctl_udp_rmem_min = SK_MEM_QUANTUM;
1708 sysctl_udp_wmem_min = SK_MEM_QUANTUM;
1709}
1710
1658EXPORT_SYMBOL(udp_disconnect); 1711EXPORT_SYMBOL(udp_disconnect);
1659EXPORT_SYMBOL(udp_hash); 1712EXPORT_SYMBOL(udp_hash);
1660EXPORT_SYMBOL(udp_hash_lock); 1713EXPORT_SYMBOL(udp_hash_lock);