]> git.itanic.dy.fi Git - linux-stable/commitdiff
af_unix: Do not use atomic ops for unix_sk(sk)->inflight.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 23 Jan 2024 17:08:53 +0000 (09:08 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Apr 2024 09:23:34 +0000 (11:23 +0200)
[ Upstream commit 97af84a6bba2ab2b9c704c08e67de3b5ea551bb2 ]

When touching unix_sk(sk)->inflight, we are always under
spin_lock(&unix_gc_lock).

Let's convert unix_sk(sk)->inflight to the normal unsigned long.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20240123170856.41348-3-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 47d8ac011fe1 ("af_unix: Fix garbage collector racing against connect()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/af_unix.h
net/unix/af_unix.c
net/unix/garbage.c
net/unix/scm.c

index afd40dce40f3d593f6fa0a11828aee9fd1582de3..d1b07ddbe677e4b745c98b8434101b7f5fe70529 100644 (file)
@@ -55,7 +55,7 @@ struct unix_sock {
        struct mutex            iolock, bindlock;
        struct sock             *peer;
        struct list_head        link;
-       atomic_long_t           inflight;
+       unsigned long           inflight;
        spinlock_t              lock;
        unsigned long           gc_flags;
 #define UNIX_GC_CANDIDATE      0
index 484874872fa6feb165ac7299044b4f4fcfd72c77..e37cf913818a1d431ef27c073ab74d55ed7ff732 100644 (file)
@@ -980,11 +980,11 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
        sk->sk_write_space      = unix_write_space;
        sk->sk_max_ack_backlog  = net->unx.sysctl_max_dgram_qlen;
        sk->sk_destruct         = unix_sock_destructor;
-       u         = unix_sk(sk);
+       u = unix_sk(sk);
+       u->inflight = 0;
        u->path.dentry = NULL;
        u->path.mnt = NULL;
        spin_lock_init(&u->lock);
-       atomic_long_set(&u->inflight, 0);
        INIT_LIST_HEAD(&u->link);
        mutex_init(&u->iolock); /* single task reading lock */
        mutex_init(&u->bindlock); /* single task binding lock */
index 027c86e804f8ac579d8e9bce139c89585641ba83..aea222796dfdcef9914b2f3a56c5ec90007699ab 100644 (file)
@@ -166,17 +166,18 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
 
 static void dec_inflight(struct unix_sock *usk)
 {
-       atomic_long_dec(&usk->inflight);
+       usk->inflight--;
 }
 
 static void inc_inflight(struct unix_sock *usk)
 {
-       atomic_long_inc(&usk->inflight);
+       usk->inflight++;
 }
 
 static void inc_inflight_move_tail(struct unix_sock *u)
 {
-       atomic_long_inc(&u->inflight);
+       u->inflight++;
+
        /* If this still might be part of a cycle, move it to the end
         * of the list, so that it's checked even if it was already
         * passed over
@@ -237,14 +238,12 @@ void unix_gc(void)
         */
        list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
                long total_refs;
-               long inflight_refs;
 
                total_refs = file_count(u->sk.sk_socket->file);
-               inflight_refs = atomic_long_read(&u->inflight);
 
-               BUG_ON(inflight_refs < 1);
-               BUG_ON(total_refs < inflight_refs);
-               if (total_refs == inflight_refs) {
+               BUG_ON(!u->inflight);
+               BUG_ON(total_refs < u->inflight);
+               if (total_refs == u->inflight) {
                        list_move_tail(&u->link, &gc_candidates);
                        __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
                        __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
@@ -271,7 +270,7 @@ void unix_gc(void)
                /* Move cursor to after the current position. */
                list_move(&cursor, &u->link);
 
-               if (atomic_long_read(&u->inflight) > 0) {
+               if (u->inflight) {
                        list_move_tail(&u->link, &not_cycle_list);
                        __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
                        scan_children(&u->sk, inc_inflight_move_tail, NULL);
index 822ce0d0d79158692c12c20eae8e1c354e1960f3..e92f2fad64105dbec3a3f8da103e73659a244b7d 100644 (file)
@@ -53,12 +53,13 @@ void unix_inflight(struct user_struct *user, struct file *fp)
        if (s) {
                struct unix_sock *u = unix_sk(s);
 
-               if (atomic_long_inc_return(&u->inflight) == 1) {
+               if (!u->inflight) {
                        BUG_ON(!list_empty(&u->link));
                        list_add_tail(&u->link, &gc_inflight_list);
                } else {
                        BUG_ON(list_empty(&u->link));
                }
+               u->inflight++;
                /* Paired with READ_ONCE() in wait_for_unix_gc() */
                WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1);
        }
@@ -75,10 +76,11 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
        if (s) {
                struct unix_sock *u = unix_sk(s);
 
-               BUG_ON(!atomic_long_read(&u->inflight));
+               BUG_ON(!u->inflight);
                BUG_ON(list_empty(&u->link));
 
-               if (atomic_long_dec_and_test(&u->inflight))
+               u->inflight--;
+               if (!u->inflight)
                        list_del_init(&u->link);
                /* Paired with READ_ONCE() in wait_for_unix_gc() */
                WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1);