net: add option to enable error queue packets waking select
authorKeller, Jacob E <jacob.e.keller@intel.com>
Thu, 28 Mar 2013 11:19:25 +0000 (11:19 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 31 Mar 2013 23:44:20 +0000 (19:44 -0400)
Currently, when a socket receives something on the error queue it only wakes up
the socket on select if it is in the "read" list, that is the socket has
something to read. It is useful also to wake the socket if it is in the error
list, which would enable software to wait on error queue packets without waking
up for regular data on the socket. The main use case is for receiving
timestamped transmit packets which return the timestamp to the socket via the
error queue. This enables an application to select on the socket for the error
queue only instead of for the regular traffic.

-v2-
* Added the SO_SELECT_ERR_QUEUE socket option to every architechture specific file
* Modified every socket poll function that checks error queue

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Cc: Jeffrey Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Matthew Vick <matthew.vick@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
23 files changed:
arch/alpha/include/uapi/asm/socket.h
arch/avr32/include/uapi/asm/socket.h
arch/cris/include/uapi/asm/socket.h
arch/frv/include/uapi/asm/socket.h
arch/h8300/include/uapi/asm/socket.h
arch/ia64/include/uapi/asm/socket.h
arch/m32r/include/uapi/asm/socket.h
arch/mips/include/uapi/asm/socket.h
arch/mn10300/include/uapi/asm/socket.h
arch/parisc/include/uapi/asm/socket.h
arch/powerpc/include/uapi/asm/socket.h
arch/s390/include/uapi/asm/socket.h
arch/sparc/include/uapi/asm/socket.h
arch/xtensa/include/uapi/asm/socket.h
include/net/sock.h
include/uapi/asm-generic/socket.h
net/bluetooth/af_bluetooth.c
net/core/datagram.c
net/core/sock.c
net/iucv/af_iucv.c
net/nfc/llcp/sock.c
net/sctp/socket.c
net/unix/af_unix.c

index c5195524d1ef8904af746889e9955271b2ff55c1..eee6ea76bdaff2d5bd2e07583e4e0259e595cda9 100644 (file)
@@ -79,4 +79,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _UAPI_ASM_SOCKET_H */
index 51c6401582ea677a1d9d211ce3652b833de9516c..37401f535126695e22af87b35739aba1242dd219 100644 (file)
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* __ASM_AVR32_SOCKET_H */
index 50692b738c756172af61ab84f2f8693495ea6655..ba409c9947bc2df933ca1d393b418f082424a57a 100644 (file)
@@ -74,6 +74,8 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_SOCKET_H */
 
 
index 595391f0f98c65e2bddbcbbe70b7e4d5062082d9..31dbb5d8e13debd569420493091189e5bc199aef 100644 (file)
@@ -72,5 +72,7 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_SOCKET_H */
 
index 43e32621da7d01ab20ad81f0c520d6ee83682434..5d1c6d0870e653e1f2cbfecf6e9ad7f6cf180741 100644 (file)
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_SOCKET_H */
index c567adc8bea535fb5bcc15156a51f4af55424bf3..6b4329f18b29f3878c7679c8a32a4a60d931904d 100644 (file)
@@ -81,4 +81,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_IA64_SOCKET_H */
index 519afa2755db5c8738bc7138f67aecc408d27fd2..2a3b59e0e171d0fb19897f561028b1f0482180b3 100644 (file)
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_M32R_SOCKET_H */
index 47132f44c9559630901ce5ca54b35220a548acf4..3b211507be7f56ffa4c125ce221a52d352f90a46 100644 (file)
@@ -90,4 +90,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _UAPI_ASM_SOCKET_H */
index 5c7c7c988544558f632a84ab5f529801a27b8963..b4ce844c9391c82dd36136c86a17141e6b5a93c0 100644 (file)
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_SOCKET_H */
index 526e4b9aece0a0480f1631bcb492c83ffac2c735..70c512a386f7df86d5f086553322d40b0baa894a 100644 (file)
@@ -71,6 +71,8 @@
 
 #define SO_LOCK_FILTER         0x4025
 
+#define SO_SELECT_ERR_QUEUE    0x4026
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
index a26dcaece509490746ab8b2a5d254125f6d4571f..a36daf3c6f9a31faac9e922d0c77b4c5fe412c37 100644 (file)
@@ -79,4 +79,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_POWERPC_SOCKET_H */
index f99eea7fff0fc4af85cf41ab1fd91ff6e402352b..2dacb306835ce217e91fe40a2c09aeae7edc05eb 100644 (file)
@@ -78,4 +78,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _ASM_SOCKET_H */
index cbbad74b2e06a0c6405ecabd4d054887b404668f..89f49b68a21c0804d6cbc55931b8beadf19f6711 100644 (file)
@@ -68,6 +68,8 @@
 
 #define SO_LOCK_FILTER         0x0028
 
+#define SO_SELECT_ERR_QUEUE    0x0029
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index 35905cb6e419a661c04e24bf205f5c4e1f1982f5..a8f44f50e651064b2358c7c8ab906a2103d38acc 100644 (file)
@@ -83,4 +83,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* _XTENSA_SOCKET_H */
index 14f6e9d19dc735135c263022fa394173e89aea6e..08f05f964737433390e898448bc27885ded905e8 100644 (file)
@@ -667,6 +667,7 @@ enum sock_flags {
                     * user-space instead.
                     */
        SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */
+       SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
index 4ef3acbba5daeba94e21ab2a9c4700c9b9cf2108..c5d2e3a1cf68743862049482406f2a49adbfb707 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_LOCK_FILTER         44
 
+#define SO_SELECT_ERR_QUEUE    45
+
 #endif /* __ASM_GENERIC_SOCKET_H */
index d3ee69b35a78267f35b8ea4a9b32d367160eea21..409902f892ff0b05e5b296dd1200e3cc3cd94fa0 100644 (file)
@@ -422,7 +422,8 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock,
                return bt_accept_poll(sk);
 
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-               mask |= POLLERR;
+               mask |= POLLERR |
+                       sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
 
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP | POLLIN | POLLRDNORM;
index 368f9c3f9dc6505e693f56066da6dcb19ec2ebd6..36da5b663514d9994a8c259f3e43bd25e4427838 100644 (file)
@@ -749,7 +749,9 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
 
        /* exceptional events? */
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-               mask |= POLLERR;
+               mask |= POLLERR |
+                       sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
+
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP | POLLIN | POLLRDNORM;
        if (sk->sk_shutdown == SHUTDOWN_MASK)
index a19e728d5fb614cdd45ad0b550d2122956c147c5..2ff5f3619a8dc17d553c70f2848db1162b50d3f0 100644 (file)
@@ -907,6 +907,10 @@ set_rcvbuf:
                sock_valbool_flag(sk, SOCK_NOFCS, valbool);
                break;
 
+       case SO_SELECT_ERR_QUEUE:
+               sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
+               break;
+
        default:
                ret = -ENOPROTOOPT;
                break;
@@ -1160,6 +1164,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                v.val = sock_flag(sk, SOCK_FILTER_LOCKED);
                break;
 
+       case SO_SELECT_ERR_QUEUE:
+               v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
+               break;
+
        default:
                return -ENOPROTOOPT;
        }
index a7d11ffe428428f25194702c5728562fd87a8e2b..f0550a38f2954c1bbd3b60609a1b994c12752cf0 100644 (file)
@@ -1461,7 +1461,8 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
                return iucv_accept_poll(sk);
 
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-               mask |= POLLERR;
+               mask |= POLLERR |
+                       sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
 
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP;
index f1b377e247fef0ee578c8a8a63139fd4ade88835..2d55e8a45958d056d6ba5a9b598bf8e4fd00a322 100644 (file)
@@ -521,7 +521,8 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
                return llcp_accept_poll(sk);
 
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-               mask |= POLLERR;
+               mask |= POLLERR |
+                       sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
 
        if (!skb_queue_empty(&sk->sk_receive_queue))
                mask |= POLLIN | POLLRDNORM;
index b9070736b8d9a24383be81b1764d191e854d3e63..dd21ae3013d82c3eab741cdd3332cddfcedef3e5 100644 (file)
@@ -6185,7 +6185,8 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
 
        /* Is there any exceptional events?  */
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-               mask |= POLLERR;
+               mask |= POLLERR |
+                       sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP | POLLIN | POLLRDNORM;
        if (sk->sk_shutdown == SHUTDOWN_MASK)
index 971282b6f6a38fd056dd65d127b85f044b7c6041..fb7a63ff71a5df9b669355151707e50d9f531a77 100644 (file)
@@ -2196,7 +2196,9 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
 
        /* exceptional events? */
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-               mask |= POLLERR;
+               mask |= POLLERR |
+                       sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
+
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP | POLLIN | POLLRDNORM;
        if (sk->sk_shutdown == SHUTDOWN_MASK)