diff options
author | David S. Miller <davem@davemloft.net> | 2009-07-16 23:21:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-16 23:21:24 -0400 |
commit | da8120355e80ddaf534adb8ed910871d97512d56 (patch) | |
tree | 9958a6c33e29b5af5faccf6650e98729151618a2 /net/core | |
parent | c86ae82605ef92594a0de809a8c588ae955fed63 (diff) | |
parent | 7fefe6a88494b00b151b5ca7bb84daaa781bbca7 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/wireless/orinoco/main.c
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/sock.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 6354863b1c68..d9eec153d531 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk) | |||
919 | af_family_keys + sk->sk_family); | 919 | af_family_keys + sk->sk_family); |
920 | } | 920 | } |
921 | 921 | ||
922 | /* | ||
923 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | ||
924 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | ||
925 | */ | ||
922 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 926 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
923 | { | 927 | { |
924 | #ifdef CONFIG_SECURITY_NETWORK | 928 | #ifdef CONFIG_SECURITY_NETWORK |
925 | void *sptr = nsk->sk_security; | 929 | void *sptr = nsk->sk_security; |
926 | #endif | 930 | #endif |
927 | 931 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | |
928 | memcpy(nsk, osk, osk->sk_prot->obj_size); | 932 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt)); |
933 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | ||
934 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | ||
929 | #ifdef CONFIG_SECURITY_NETWORK | 935 | #ifdef CONFIG_SECURITY_NETWORK |
930 | nsk->sk_security = sptr; | 936 | nsk->sk_security = sptr; |
931 | security_sk_clone(osk, nsk); | 937 | security_sk_clone(osk, nsk); |
@@ -939,8 +945,23 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, | |||
939 | struct kmem_cache *slab; | 945 | struct kmem_cache *slab; |
940 | 946 | ||
941 | slab = prot->slab; | 947 | slab = prot->slab; |
942 | if (slab != NULL) | 948 | if (slab != NULL) { |
943 | sk = kmem_cache_alloc(slab, priority); | 949 | sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO); |
950 | if (!sk) | ||
951 | return sk; | ||
952 | if (priority & __GFP_ZERO) { | ||
953 | /* | ||
954 | * caches using SLAB_DESTROY_BY_RCU should let | ||
955 | * sk_node.next un-modified. Special care is taken | ||
956 | * when initializing object to zero. | ||
957 | */ | ||
958 | if (offsetof(struct sock, sk_node.next) != 0) | ||
959 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
960 | memset(&sk->sk_node.pprev, 0, | ||
961 | prot->obj_size - offsetof(struct sock, | ||
962 | sk_node.pprev)); | ||
963 | } | ||
964 | } | ||
944 | else | 965 | else |
945 | sk = kmalloc(prot->obj_size, priority); | 966 | sk = kmalloc(prot->obj_size, priority); |
946 | 967 | ||
@@ -1125,6 +1146,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1125 | 1146 | ||
1126 | newsk->sk_err = 0; | 1147 | newsk->sk_err = 0; |
1127 | newsk->sk_priority = 0; | 1148 | newsk->sk_priority = 0; |
1149 | /* | ||
1150 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1151 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1152 | */ | ||
1153 | smp_wmb(); | ||
1128 | atomic_set(&newsk->sk_refcnt, 2); | 1154 | atomic_set(&newsk->sk_refcnt, 2); |
1129 | 1155 | ||
1130 | /* | 1156 | /* |
@@ -1840,6 +1866,11 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1840 | 1866 | ||
1841 | sk->sk_stamp = ktime_set(-1L, 0); | 1867 | sk->sk_stamp = ktime_set(-1L, 0); |
1842 | 1868 | ||
1869 | /* | ||
1870 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1871 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1872 | */ | ||
1873 | smp_wmb(); | ||
1843 | atomic_set(&sk->sk_refcnt, 1); | 1874 | atomic_set(&sk->sk_refcnt, 1); |
1844 | atomic_set(&sk->sk_wmem_alloc, 1); | 1875 | atomic_set(&sk->sk_wmem_alloc, 1); |
1845 | atomic_set(&sk->sk_drops, 0); | 1876 | atomic_set(&sk->sk_drops, 0); |