|
@@ -1009,6 +1009,36 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes
|
|
|
+ * un-modified. Special care is taken when initializing object to zero.
|
|
|
+ */
|
|
|
+static inline void sk_prot_clear_nulls(struct sock *sk, int size)
|
|
|
+{
|
|
|
+ if (offsetof(struct sock, sk_node.next) != 0)
|
|
|
+ memset(sk, 0, offsetof(struct sock, sk_node.next));
|
|
|
+ memset(&sk->sk_node.pprev, 0,
|
|
|
+ size - offsetof(struct sock, sk_node.pprev));
|
|
|
+}
|
|
|
+
|
|
|
+void sk_prot_clear_portaddr_nulls(struct sock *sk, int size)
|
|
|
+{
|
|
|
+ unsigned long nulls1, nulls2;
|
|
|
+
|
|
|
+ nulls1 = offsetof(struct sock, __sk_common.skc_node.next);
|
|
|
+ nulls2 = offsetof(struct sock, __sk_common.skc_portaddr_node.next);
|
|
|
+ if (nulls1 > nulls2)
|
|
|
+ swap(nulls1, nulls2);
|
|
|
+
|
|
|
+ if (nulls1 != 0)
|
|
|
+ memset((char *)sk, 0, nulls1);
|
|
|
+ memset((char *)sk + nulls1 + sizeof(void *), 0,
|
|
|
+ nulls2 - nulls1 - sizeof(void *));
|
|
|
+ memset((char *)sk + nulls2 + sizeof(void *), 0,
|
|
|
+ size - nulls2 - sizeof(void *));
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(sk_prot_clear_portaddr_nulls);
|
|
|
+
|
|
|
static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
|
|
|
int family)
|
|
|
{
|
|
@@ -1021,19 +1051,12 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
|
|
|
if (!sk)
|
|
|
return sk;
|
|
|
if (priority & __GFP_ZERO) {
|
|
|
- /*
|
|
|
- * caches using SLAB_DESTROY_BY_RCU should let
|
|
|
- * sk_node.next un-modified. Special care is taken
|
|
|
- * when initializing object to zero.
|
|
|
- */
|
|
|
- if (offsetof(struct sock, sk_node.next) != 0)
|
|
|
- memset(sk, 0, offsetof(struct sock, sk_node.next));
|
|
|
- memset(&sk->sk_node.pprev, 0,
|
|
|
- prot->obj_size - offsetof(struct sock,
|
|
|
- sk_node.pprev));
|
|
|
+ if (prot->clear_sk)
|
|
|
+ prot->clear_sk(sk, prot->obj_size);
|
|
|
+ else
|
|
|
+ sk_prot_clear_nulls(sk, prot->obj_size);
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
+ } else
|
|
|
sk = kmalloc(prot->obj_size, priority);
|
|
|
|
|
|
if (sk != NULL) {
|