io_uring/poll: add requeue return code from poll multishot handling
[platform/kernel/linux-starfive.git] / net / rose / af_rose.c
index 49dafe9..42e8b9e 100644 (file)
@@ -182,21 +182,47 @@ void rose_kill_by_neigh(struct rose_neigh *neigh)
  */
 static void rose_kill_by_device(struct net_device *dev)
 {
-       struct sock *s;
+       struct sock *sk, *array[16];
+       struct rose_sock *rose;
+       bool rescan;
+       int i, cnt;
 
+start:
+       rescan = false;
+       cnt = 0;
        spin_lock_bh(&rose_list_lock);
-       sk_for_each(s, &rose_list) {
-               struct rose_sock *rose = rose_sk(s);
+       sk_for_each(sk, &rose_list) {
+               rose = rose_sk(sk);
+               if (rose->device == dev) {
+                       if (cnt == ARRAY_SIZE(array)) {
+                               rescan = true;
+                               break;
+                       }
+                       sock_hold(sk);
+                       array[cnt++] = sk;
+               }
+       }
+       spin_unlock_bh(&rose_list_lock);
 
+       for (i = 0; i < cnt; i++) {
+               sk = array[cnt];
+               rose = rose_sk(sk);
+               lock_sock(sk);
+               spin_lock_bh(&rose_list_lock);
                if (rose->device == dev) {
-                       rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
+                       rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
                        if (rose->neighbour)
                                rose->neighbour->use--;
                        netdev_put(rose->device, &rose->dev_tracker);
                        rose->device = NULL;
                }
+               spin_unlock_bh(&rose_list_lock);
+               release_sock(sk);
+               sock_put(sk);
+               cond_resched();
        }
-       spin_unlock_bh(&rose_list_lock);
+       if (rescan)
+               goto start;
 }
 
 /*
@@ -656,7 +682,10 @@ static int rose_release(struct socket *sock)
                break;
        }
 
+       spin_lock_bh(&rose_list_lock);
        netdev_put(rose->device, &rose->dev_tracker);
+       rose->device = NULL;
+       spin_unlock_bh(&rose_list_lock);
        sock->sk = NULL;
        release_sock(sk);
        sock_put(sk);
@@ -1315,9 +1344,11 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        case TIOCINQ: {
                struct sk_buff *skb;
                long amount = 0L;
-               /* These two are safe on a single CPU system as only user tasks fiddle here */
+
+               spin_lock_irq(&sk->sk_receive_queue.lock);
                if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                        amount = skb->len;
+               spin_unlock_irq(&sk->sk_receive_queue.lock);
                return put_user(amount, (unsigned int __user *) argp);
        }