Commit 151b98d1 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Jakub Kicinski
Browse files

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: default avatarKuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: default avatarXin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20251023231751.4168390-5-kuniyu@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b7185792
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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);
+16 −8
Original line number Diff line number Diff line
@@ -2462,13 +2462,16 @@ static void sk_init_common(struct sock *sk)
}

/**
 *	sk_clone_lock - clone a socket, and lock its clone
 * 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);

	if (lock)
		bh_lock_sock(newsk);

	newsk->sk_backlog.head	= newsk->sk_backlog.tail = NULL;
	newsk->sk_backlog.len = 0;

@@ -2590,12 +2597,13 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
	 * destructor and make plain sk_free()
	 */
	newsk->sk_destruct = NULL;
	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)
{