mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
net: Add sk_clone().
sctp_accept() will use sk_clone_lock(), but it will be called with the parent socket locked, and sctp_migrate() acquires the child lock later. Let's add no lock version of sk_clone_lock(). Note that lockdep complains if we simply use bh_lock_sock_nested(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Xin Long <lucien.xin@gmail.com> Link: https://patch.msgid.link/20251023231751.4168390-5-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
b7185792f8
commit
151b98d10e
@@ -1822,7 +1822,12 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
|
||||
void sk_free(struct sock *sk);
|
||||
void sk_net_refcnt_upgrade(struct sock *sk);
|
||||
void sk_destruct(struct sock *sk);
|
||||
struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority);
|
||||
struct sock *sk_clone(const struct sock *sk, const gfp_t priority, bool lock);
|
||||
|
||||
static inline struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
|
||||
{
|
||||
return sk_clone(sk, priority, true);
|
||||
}
|
||||
|
||||
struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
|
||||
gfp_t priority);
|
||||
|
||||
@@ -2462,13 +2462,16 @@ static void sk_init_common(struct sock *sk)
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_clone_lock - clone a socket, and lock its clone
|
||||
* @sk: the socket to clone
|
||||
* @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
|
||||
* sk_clone - clone a socket
|
||||
* @sk: the socket to clone
|
||||
* @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
|
||||
* @lock: if true, lock the cloned sk
|
||||
*
|
||||
* Caller must unlock socket even in error path (bh_unlock_sock(newsk))
|
||||
* If @lock is true, the clone is locked by bh_lock_sock(), and
|
||||
* caller must unlock socket even in error path by bh_unlock_sock().
|
||||
*/
|
||||
struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
|
||||
struct sock *sk_clone(const struct sock *sk, const gfp_t priority,
|
||||
bool lock)
|
||||
{
|
||||
struct proto *prot = READ_ONCE(sk->sk_prot);
|
||||
struct sk_filter *filter;
|
||||
@@ -2497,9 +2500,13 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
|
||||
__netns_tracker_alloc(sock_net(newsk), &newsk->ns_tracker,
|
||||
false, priority);
|
||||
}
|
||||
|
||||
sk_node_init(&newsk->sk_node);
|
||||
sock_lock_init(newsk);
|
||||
bh_lock_sock(newsk);
|
||||
|
||||
if (lock)
|
||||
bh_lock_sock(newsk);
|
||||
|
||||
newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
|
||||
newsk->sk_backlog.len = 0;
|
||||
|
||||
@@ -2590,12 +2597,13 @@ free:
|
||||
* destructor and make plain sk_free()
|
||||
*/
|
||||
newsk->sk_destruct = NULL;
|
||||
bh_unlock_sock(newsk);
|
||||
if (lock)
|
||||
bh_unlock_sock(newsk);
|
||||
sk_free(newsk);
|
||||
newsk = NULL;
|
||||
goto out;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sk_clone_lock);
|
||||
EXPORT_SYMBOL_GPL(sk_clone);
|
||||
|
||||
static u32 sk_dst_gso_max_size(struct sock *sk, const struct net_device *dev)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user