struct sock *sk_alloc(int family, int priority, int zero_it) { struct sock *sk = kmem_cache_alloc(sk_cachep, priority); if(sk && zero_it) { memset(sk, 0, sizeof(struct sock)); sk->family = family; sock_lock_init(sk); } return sk; }
/** * sk_alloc - All socket objects are allocated here * @family - protocol family * @priority - for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) * @zero_it - zeroes the allocated sock * @slab - alternate slab * * All socket objects are allocated here. If @zero_it is non-zero * it should have the size of the are to be zeroed, because the * private slabcaches have different sizes of the generic struct sock. * 1 has been kept as a way to say sizeof(struct sock). */ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab) { struct sock *sk = NULL; if (!slab) slab = sk_cachep; sk = kmem_cache_alloc(slab, priority); if (sk) { if (zero_it) { memset(sk, 0, zero_it == 1 ? sizeof(struct sock) : zero_it); sk->sk_family = family; sock_lock_init(sk); } sk->sk_slab = slab; } return sk; }
/** * sk_alloc - All socket objects are allocated here * @family: protocol family * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) * @prot: struct proto associated with this new sock instance * @zero_it: if we should zero the newly allocated sock */ struct sock *sk_alloc(int family, gfp_t priority, struct proto *prot, int zero_it) { struct sock *sk = NULL; kmem_cache_t *slab = prot->slab; if (slab != NULL) sk = kmem_cache_alloc(slab, priority); else sk = kmalloc(prot->obj_size, priority); if (sk) { if (zero_it) { memset(sk, 0, prot->obj_size); sk->sk_family = family; /* * See comment in struct sock definition to understand * why we need sk_prot_creator -acme */ sk->sk_prot = sk->sk_prot_creator = prot; sock_lock_init(sk); } if (security_sk_alloc(sk, family, priority)) goto out_free; if (!try_module_get(prot->owner)) goto out_free; } return sk; out_free: if (slab != NULL) kmem_cache_free(slab, sk); else kfree(sk); return NULL; }
struct sock *sk_clone(struct sock *sk, const gfp_t priority) { struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0); if (newsk != NULL) { struct sk_filter *filter; memcpy(newsk, sk, sk->sk_prot->obj_size); /* SANITY */ sk_node_init(&newsk->sk_node); sock_lock_init(newsk); bh_lock_sock(newsk); atomic_set(&newsk->sk_rmem_alloc, 0); atomic_set(&newsk->sk_wmem_alloc, 0); atomic_set(&newsk->sk_omem_alloc, 0); skb_queue_head_init(&newsk->sk_receive_queue); skb_queue_head_init(&newsk->sk_write_queue); rwlock_init(&newsk->sk_dst_lock); rwlock_init(&newsk->sk_callback_lock); newsk->sk_dst_cache = NULL; newsk->sk_wmem_queued = 0; newsk->sk_forward_alloc = 0; newsk->sk_send_head = NULL; newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; sock_reset_flag(newsk, SOCK_DONE); skb_queue_head_init(&newsk->sk_error_queue); filter = newsk->sk_filter; if (filter != NULL) sk_filter_charge(newsk, filter); if (sk->sk_create_child) sk->sk_create_child(sk, newsk); if (unlikely(xfrm_sk_clone_policy(newsk))) { /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ newsk->sk_destruct = NULL; sk_free(newsk); newsk = NULL; goto out; } newsk->sk_err = 0; newsk->sk_priority = 0; atomic_set(&newsk->sk_refcnt, 2); /* * Increment the counter in the same struct proto as the master * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that * is the same as sk->sk_prot->socks, as this field was copied * with memcpy). * * This _changes_ the previous behaviour, where * tcp_create_openreq_child always was incrementing the * equivalent to tcp_prot->socks (inet_sock_nr), so this have * to be taken into account in all callers. -acme */ sk_refcnt_debug_inc(newsk); newsk->sk_socket = NULL; newsk->sk_sleep = NULL; if (newsk->sk_prot->sockets_allocated) atomic_inc(newsk->sk_prot->sockets_allocated); } out: return newsk; }