unix: uses an atomic type for scm files accounting
authorPaolo Abeni <pabeni@redhat.com>
Fri, 28 Feb 2020 13:45:21 +0000 (14:45 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 28 Feb 2020 20:12:53 +0000 (12:12 -0800)
So the scm_stat_{add,del} helper can be invoked with no
additional lock held.

This clean-up the code a bit and will make the next
patch easier.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/af_unix.h
net/unix/af_unix.c

index e51d727..f42fddd 100644 (file)
@@ -42,7 +42,7 @@ struct unix_skb_parms {
 } __randomize_layout;
 
 struct scm_stat {
-       u32 nr_fds;
+       atomic_t nr_fds;
 };
 
 #define UNIXCB(skb)    (*(struct unix_skb_parms *)&((skb)->cb))
index 9d0518d..c46fa27 100644 (file)
@@ -690,7 +690,8 @@ static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
 
        if (sk) {
                u = unix_sk(sock->sk);
-               seq_printf(m, "scm_fds: %u\n", READ_ONCE(u->scm_stat.nr_fds));
+               seq_printf(m, "scm_fds: %u\n",
+                          atomic_read(&u->scm_stat.nr_fds));
        }
 }
 #else
@@ -1602,10 +1603,8 @@ static void scm_stat_add(struct sock *sk, struct sk_buff *skb)
        struct scm_fp_list *fp = UNIXCB(skb).fp;
        struct unix_sock *u = unix_sk(sk);
 
-       lockdep_assert_held(&sk->sk_receive_queue.lock);
-
        if (unlikely(fp && fp->count))
-               u->scm_stat.nr_fds += fp->count;
+               atomic_add(fp->count, &u->scm_stat.nr_fds);
 }
 
 static void scm_stat_del(struct sock *sk, struct sk_buff *skb)
@@ -1613,10 +1612,8 @@ static void scm_stat_del(struct sock *sk, struct sk_buff *skb)
        struct scm_fp_list *fp = UNIXCB(skb).fp;
        struct unix_sock *u = unix_sk(sk);
 
-       lockdep_assert_held(&sk->sk_receive_queue.lock);
-
        if (unlikely(fp && fp->count))
-               u->scm_stat.nr_fds -= fp->count;
+               atomic_sub(fp->count, &u->scm_stat.nr_fds);
 }
 
 /*
@@ -1805,10 +1802,8 @@ restart_locked:
        if (sock_flag(other, SOCK_RCVTSTAMP))
                __net_timestamp(skb);
        maybe_add_creds(skb, sock, other);
-       spin_lock(&other->sk_receive_queue.lock);
        scm_stat_add(other, skb);
-       __skb_queue_tail(&other->sk_receive_queue, skb);
-       spin_unlock(&other->sk_receive_queue.lock);
+       skb_queue_tail(&other->sk_receive_queue, skb);
        unix_state_unlock(other);
        other->sk_data_ready(other);
        sock_put(other);
@@ -1910,10 +1905,8 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                        goto pipe_err_free;
 
                maybe_add_creds(skb, sock, other);
-               spin_lock(&other->sk_receive_queue.lock);
                scm_stat_add(other, skb);
-               __skb_queue_tail(&other->sk_receive_queue, skb);
-               spin_unlock(&other->sk_receive_queue.lock);
+               skb_queue_tail(&other->sk_receive_queue, skb);
                unix_state_unlock(other);
                other->sk_data_ready(other);
                sent += size;
@@ -2409,9 +2402,7 @@ unlock:
                        sk_peek_offset_bwd(sk, chunk);
 
                        if (UNIXCB(skb).fp) {
-                               spin_lock(&sk->sk_receive_queue.lock);
                                scm_stat_del(sk, skb);
-                               spin_unlock(&sk->sk_receive_queue.lock);
                                unix_detach_fds(&scm, skb);
                        }