[NET]: Avoid atomic xchg() for non-error case
Benjamin LaHaise [Wed, 14 Dec 2005 07:22:19 +0000 (23:22 -0800)]
It also looks like there were 2 places where the test on sk_err was
missing from the event wait logic (in sk_stream_wait_connect and
sk_stream_wait_memory), while the rest of the sock_error() users look
to be doing the right thing.  This version of the patch fixes those,
and cleans up a few places that were testing ->sk_err directly.

Signed-off-by: Benjamin LaHaise <benjamin.c.lahaise@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/net/sock.h
net/bluetooth/af_bluetooth.c
net/bluetooth/l2cap.c
net/bluetooth/sco.c
net/core/stream.c
net/irda/af_irda.c
net/llc/af_llc.c

index 982b4ec..0fbae85 100644 (file)
@@ -1166,7 +1166,10 @@ static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
  
 static inline int sock_error(struct sock *sk)
 {
-       int err = xchg(&sk->sk_err, 0);
+       int err;
+       if (likely(!sk->sk_err))
+               return 0;
+       err = xchg(&sk->sk_err, 0);
        return -err;
 }
 
index ea616e3..fb031fe 100644 (file)
@@ -287,10 +287,9 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
                timeo = schedule_timeout(timeo);
                lock_sock(sk);
 
-               if (sk->sk_err) {
-                       err = sock_error(sk);
+               err = sock_error(sk);
+               if (err)
                        break;
-               }
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(sk->sk_sleep, &wait);
index e3bb11c..95f33cc 100644 (file)
@@ -767,8 +767,9 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
        BT_DBG("sock %p, sk %p", sock, sk);
 
-       if (sk->sk_err)
-               return sock_error(sk);
+       err = sock_error(sk);
+       if (err)
+               return err;
 
        if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
index 9cb00dc..6481814 100644 (file)
@@ -637,8 +637,9 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 
        BT_DBG("sock %p, sk %p", sock, sk);
 
-       if (sk->sk_err)
-               return sock_error(sk);
+       err = sock_error(sk);
+       if (err)
+               return err;
 
        if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
index 15bfd03..35e2525 100644 (file)
@@ -55,8 +55,9 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
        int done;
 
        do {
-               if (sk->sk_err)
-                       return sock_error(sk);
+               int err = sock_error(sk);
+               if (err)
+                       return err;
                if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
                        return -EPIPE;
                if (!*timeo_p)
@@ -67,6 +68,7 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
                prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
                sk->sk_write_pending++;
                done = sk_wait_event(sk, timeo_p,
+                                    !sk->sk_err &&
                                     !((1 << sk->sk_state) & 
                                       ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)));
                finish_wait(sk->sk_sleep, &wait);
@@ -137,7 +139,9 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
 
                set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
                sk->sk_write_pending++;
-               sk_wait_event(sk, &current_timeo, sk_stream_memory_free(sk) &&
+               sk_wait_event(sk, &current_timeo, !sk->sk_err && 
+                                                 !(sk->sk_shutdown & SEND_SHUTDOWN) &&
+                                                 sk_stream_memory_free(sk) &&
                                                  vm_wait);
                sk->sk_write_pending--;
 
index 6f92f9c..f121f7d 100644 (file)
@@ -1438,8 +1438,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
                        /*
                         *      POSIX 1003.1g mandates this order.
                         */
-                       if (sk->sk_err)
-                               ret = sock_error(sk);
+                       ret = sock_error(sk);
+                       if (ret)
+                               break;
                        else if (sk->sk_shutdown & RCV_SHUTDOWN)
                                ;
                        else if (noblock)
index c3f0b07..b6d3df5 100644 (file)
@@ -566,10 +566,9 @@ static int llc_wait_data(struct sock *sk, long timeo)
                /*
                 * POSIX 1003.1g mandates this order.
                 */
-               if (sk->sk_err) {
-                       rc = sock_error(sk);
+               rc = sock_error(sk);
+               if (rc)
                        break;
-               }
                rc = 0;
                if (sk->sk_shutdown & RCV_SHUTDOWN)
                        break;