* [PATCH v1 net-next 0/2] af_unix: Clean up unnecessary spin_lock(&sk->sk_peer_lock).
@ 2024-01-28 10:37 Kuniyuki Iwashima
2024-01-28 10:37 ` [PATCH v1 net-next 1/2] af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket Kuniyuki Iwashima
2024-01-28 10:37 ` [PATCH v1 net-next 2/2] af_unix: Don't hold client's sk_peer_lock in copy_peercred() Kuniyuki Iwashima
0 siblings, 2 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2024-01-28 10:37 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Kent Overstreet, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev
Except for updating sk_peer_pid/sk_peer_cred, we do not need to hold
sk_peer_lock during initialisation.
This series removes unnecessary spin_lock() and spin_unlock() in such
places.
Kuniyuki Iwashima (2):
af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket.
af_unix: Don't hold client's sk_peer_lock in copy_peercred().
net/unix/af_unix.c | 31 ++++++++++---------------------
1 file changed, 10 insertions(+), 21 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v1 net-next 1/2] af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket.
2024-01-28 10:37 [PATCH v1 net-next 0/2] af_unix: Clean up unnecessary spin_lock(&sk->sk_peer_lock) Kuniyuki Iwashima
@ 2024-01-28 10:37 ` Kuniyuki Iwashima
2024-01-28 10:37 ` [PATCH v1 net-next 2/2] af_unix: Don't hold client's sk_peer_lock in copy_peercred() Kuniyuki Iwashima
1 sibling, 0 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2024-01-28 10:37 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Kent Overstreet, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev
init_peercred() is called in 3 places:
1. socketpair() : both sockets
2. connect() : child socket
3. listen() : listening socket
The first two need not hold sk_peer_lock because no one can
touch the socket.
Let's set cred/pid without holding lock for the two cases and
rename the old init_peercred() to update_peercred() to properly
reflect the use case.
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
net/unix/af_unix.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 1720419d93d6..f07374d31f7c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -684,6 +684,12 @@ static void unix_release_sock(struct sock *sk, int embrion)
}
static void init_peercred(struct sock *sk)
+{
+ sk->sk_peer_pid = get_pid(task_tgid(current));
+ sk->sk_peer_cred = get_current_cred();
+}
+
+static void update_peercred(struct sock *sk)
{
const struct cred *old_cred;
struct pid *old_pid;
@@ -691,8 +697,7 @@ static void init_peercred(struct sock *sk)
spin_lock(&sk->sk_peer_lock);
old_pid = sk->sk_peer_pid;
old_cred = sk->sk_peer_cred;
- sk->sk_peer_pid = get_pid(task_tgid(current));
- sk->sk_peer_cred = get_current_cred();
+ init_peercred(sk);
spin_unlock(&sk->sk_peer_lock);
put_pid(old_pid);
@@ -743,7 +748,7 @@ static int unix_listen(struct socket *sock, int backlog)
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
/* set credentials so connect can copy them */
- init_peercred(sk);
+ update_peercred(sk);
err = 0;
out_unlock:
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v1 net-next 2/2] af_unix: Don't hold client's sk_peer_lock in copy_peercred().
2024-01-28 10:37 [PATCH v1 net-next 0/2] af_unix: Clean up unnecessary spin_lock(&sk->sk_peer_lock) Kuniyuki Iwashima
2024-01-28 10:37 ` [PATCH v1 net-next 1/2] af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket Kuniyuki Iwashima
@ 2024-01-28 10:37 ` Kuniyuki Iwashima
2024-01-28 21:04 ` Kuniyuki Iwashima
1 sibling, 1 reply; 4+ messages in thread
From: Kuniyuki Iwashima @ 2024-01-28 10:37 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Kent Overstreet, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev
When (AF_UNIX, SOCK_STREAM) socket connect()s to a listening socket,
the listener's sk_peer_pid/sk_peer_cred are copied to the client in
copy_peercred().
Then, two sk_peer_locks are held there; one is client's and another
is listener's. However, we need not hold the client's lock.
The only place where the client's sk_peer_pid/sk_peer_cred are set
is copy_peercred(), and once they are set, they never change.
Let's not hold client's sk_peer_lock in copy_peercred().
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
net/unix/af_unix.c | 20 ++------------------
1 file changed, 2 insertions(+), 18 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f07374d31f7c..c5c292393be8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -706,26 +706,10 @@ static void update_peercred(struct sock *sk)
static void copy_peercred(struct sock *sk, struct sock *peersk)
{
- const struct cred *old_cred;
- struct pid *old_pid;
-
- if (sk < peersk) {
- spin_lock(&sk->sk_peer_lock);
- spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING);
- } else {
- spin_lock(&peersk->sk_peer_lock);
- spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING);
- }
- old_pid = sk->sk_peer_pid;
- old_cred = sk->sk_peer_cred;
- sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
+ spin_lock(&peersk->sk_peer_lock);
+ sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
-
- spin_unlock(&sk->sk_peer_lock);
spin_unlock(&peersk->sk_peer_lock);
-
- put_pid(old_pid);
- put_cred(old_cred);
}
static int unix_listen(struct socket *sock, int backlog)
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v1 net-next 2/2] af_unix: Don't hold client's sk_peer_lock in copy_peercred().
2024-01-28 10:37 ` [PATCH v1 net-next 2/2] af_unix: Don't hold client's sk_peer_lock in copy_peercred() Kuniyuki Iwashima
@ 2024-01-28 21:04 ` Kuniyuki Iwashima
0 siblings, 0 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2024-01-28 21:04 UTC (permalink / raw)
To: kuniyu; +Cc: davem, edumazet, kent.overstreet, kuba, kuni1840, netdev, pabeni
From: Kuniyuki Iwashima <kuniyu@amazon.com>
Date: Sun, 28 Jan 2024 02:37:32 -0800
> When (AF_UNIX, SOCK_STREAM) socket connect()s to a listening socket,
> the listener's sk_peer_pid/sk_peer_cred are copied to the client in
> copy_peercred().
>
> Then, two sk_peer_locks are held there; one is client's and another
> is listener's. However, we need not hold the client's lock.
>
> The only place where the client's sk_peer_pid/sk_peer_cred are set
> is copy_peercred(), and once they are set, they never change.
>
> Let's not hold client's sk_peer_lock in copy_peercred().
>
> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
> ---
> net/unix/af_unix.c | 20 ++------------------
> 1 file changed, 2 insertions(+), 18 deletions(-)
>
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index f07374d31f7c..c5c292393be8 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -706,26 +706,10 @@ static void update_peercred(struct sock *sk)
>
> static void copy_peercred(struct sock *sk, struct sock *peersk)
> {
> - const struct cred *old_cred;
> - struct pid *old_pid;
> -
> - if (sk < peersk) {
> - spin_lock(&sk->sk_peer_lock);
> - spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING);
> - } else {
> - spin_lock(&peersk->sk_peer_lock);
> - spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING);
Somehow I forgot about that the client's sk_peer_pid could be
fetched at the same time by SO_PEERCRED/SO_PEERPIDFD, so the
lock is needed.
> - }
> - old_pid = sk->sk_peer_pid;
> - old_cred = sk->sk_peer_cred;
but old_pid/old_cred are always NULL, so this can be removed.
Also, the locking order can be fixed as
peer (TCP_LISTEN) -> sk (TCP_ESTABLISHED)
and we can write a lock_cmp_fn for sk_peer_lock.
I'll do so in v2, so
pw-bot: cr
> - sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
> + spin_lock(&peersk->sk_peer_lock);
> + sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
> sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
> -
> - spin_unlock(&sk->sk_peer_lock);
> spin_unlock(&peersk->sk_peer_lock);
> -
> - put_pid(old_pid);
> - put_cred(old_cred);
> }
>
> static int unix_listen(struct socket *sock, int backlog)
> --
> 2.30.2
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-01-28 21:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-28 10:37 [PATCH v1 net-next 0/2] af_unix: Clean up unnecessary spin_lock(&sk->sk_peer_lock) Kuniyuki Iwashima
2024-01-28 10:37 ` [PATCH v1 net-next 1/2] af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket Kuniyuki Iwashima
2024-01-28 10:37 ` [PATCH v1 net-next 2/2] af_unix: Don't hold client's sk_peer_lock in copy_peercred() Kuniyuki Iwashima
2024-01-28 21:04 ` Kuniyuki Iwashima
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).