net: add socket option for low latency polling
authorEliezer Tamir <eliezer.tamir@linux.intel.com>
Fri, 14 Jun 2013 13:33:57 +0000 (16:33 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Jun 2013 22:48:14 +0000 (15:48 -0700)
adds a socket option for low latency polling.
This allows overriding the global sysctl value with a per-socket one.
Unexport sysctl_net_ll_poll since for now it's not needed in modules.

Signed-off-by: Eliezer Tamir <eliezer.tamir@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
19 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/ll_poll.h
include/net/sock.h
include/uapi/asm-generic/socket.h
net/core/sock.c
net/socket.c

index eee6ea76bdaff2d5bd2e07583e4e0259e595cda9..4885825e498d754b6efb891d1e28a9e9f8536dbc 100644 (file)
@@ -81,4 +81,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _UAPI_ASM_SOCKET_H */
index 37401f535126695e22af87b35739aba1242dd219..79b61798ebf8abce4d89150296ab879280933a9e 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* __ASM_AVR32_SOCKET_H */
index ba409c9947bc2df933ca1d393b418f082424a57a..47b1ec55092d62cb6df800a7c0ef5250c016ebbd 100644 (file)
@@ -76,6 +76,8 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_SOCKET_H */
 
 
index 31dbb5d8e13debd569420493091189e5bc199aef..dbc08520f22c581cfd20d3376d40b590486caf18 100644 (file)
@@ -74,5 +74,7 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_SOCKET_H */
 
index 5d1c6d0870e653e1f2cbfecf6e9ad7f6cf180741..a38d38a6520bfcc58fb3b4729cb1e38ecc37aa90 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_SOCKET_H */
index 6b4329f18b29f3878c7679c8a32a4a60d931904d..d3358b7606819bcc733affa863febe620ad90f4b 100644 (file)
@@ -83,4 +83,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_IA64_SOCKET_H */
index 2a3b59e0e171d0fb19897f561028b1f0482180b3..44aaf4639a4a0c5c9364ec4e609200b9be5e553e 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_M32R_SOCKET_H */
index 3b211507be7f56ffa4c125ce221a52d352f90a46..6a07992ba6c6b0e6f9b577e7693a8dfebaed7a8c 100644 (file)
@@ -92,4 +92,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _UAPI_ASM_SOCKET_H */
index b4ce844c9391c82dd36136c86a17141e6b5a93c0..db80fd3e398b8abf0321db0d08f9d1ec248cb001 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_SOCKET_H */
index 70c512a386f7df86d5f086553322d40b0baa894a..f866fff9a00411c7d45111bd9f780a53846615b5 100644 (file)
@@ -73,6 +73,8 @@
 
 #define SO_SELECT_ERR_QUEUE    0x4026
 
+#define SO_LL                  0x4027
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
index a36daf3c6f9a31faac9e922d0c77b4c5fe412c37..405fb09bda94184de0876d46fb9ee3618d5bece8 100644 (file)
@@ -81,4 +81,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_POWERPC_SOCKET_H */
index 2dacb306835ce217e91fe40a2c09aeae7edc05eb..0c5105fbaaf335f32f3134ef0acc74bd853fbab6 100644 (file)
@@ -80,4 +80,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _ASM_SOCKET_H */
index 89f49b68a21c0804d6cbc55931b8beadf19f6711..b46c3fa0b2653ff93ce0af66eca6df2b2d3a1277 100644 (file)
@@ -70,6 +70,8 @@
 
 #define SO_SELECT_ERR_QUEUE    0x0029
 
+#define SO_LL                  0x0030
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index a8f44f50e651064b2358c7c8ab906a2103d38acc..b21ace4fc9bab09ef3aa58170a0ac3e0d814dc3d 100644 (file)
@@ -85,4 +85,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* _XTENSA_SOCKET_H */
index 6930cbd943e214df92bab4ef2359cdf0b584ca80..fcc7c365cee576ecf4ef1d0f1765b3155e3f52f9 100644 (file)
@@ -39,12 +39,12 @@ extern unsigned int sysctl_net_ll_poll __read_mostly;
 /* we can use sched_clock() because we don't care much about precision
  * we only care that the average is bounded
  */
-static inline u64 ll_end_time(void)
+static inline u64 ll_end_time(struct sock *sk)
 {
-       u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll);
+       u64 end_time = ACCESS_ONCE(sk->sk_ll_usec);
 
        /* we don't mind a ~2.5% imprecision
-        * sysctl_net_ll_poll is a u_int so this can't overflow
+        * sk->sk_ll_usec is a u_int so this can't overflow
         */
        end_time = (end_time << 10) + sched_clock();
 
@@ -53,7 +53,7 @@ static inline u64 ll_end_time(void)
 
 static inline bool sk_valid_ll(struct sock *sk)
 {
-       return sysctl_net_ll_poll && sk->sk_napi_id &&
+       return sk->sk_ll_usec && sk->sk_napi_id &&
               !need_resched() && !signal_pending(current);
 }
 
@@ -65,7 +65,7 @@ static inline bool can_poll_ll(u64 end_time)
 static inline bool sk_poll_ll(struct sock *sk, int nonblock)
 {
        const struct net_device_ops *ops;
-       u64 end_time = ll_end_time();
+       u64 end_time = ll_end_time(sk);
        struct napi_struct *napi;
        int rc = false;
 
@@ -118,7 +118,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb)
 
 #else /* CONFIG_NET_LL_RX_POLL */
 
-static inline u64 ll_end_time(void)
+static inline u64 ll_end_time(struct sock *sk)
 {
        return 0;
 }
index ac8e1818380c2c2a669cd9725dd4f018d86092b5..21db792bffa5be5971124f622e936017306ce247 100644 (file)
@@ -230,6 +230,7 @@ struct cg_proto;
   *    @sk_wmem_queued: persistent queue size
   *    @sk_forward_alloc: space allocated forward
   *    @sk_napi_id: id of the last napi context to receive data for sk
+  *    @sk_ll_usec: usecs to busypoll when there is no data
   *    @sk_allocation: allocation mode
   *    @sk_sndbuf: size of send buffer in bytes
   *    @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
@@ -328,6 +329,7 @@ struct sock {
 #endif
 #ifdef CONFIG_NET_LL_RX_POLL
        unsigned int            sk_napi_id;
+       unsigned int            sk_ll_usec;
 #endif
        atomic_t                sk_drops;
        int                     sk_rcvbuf;
index c5d2e3a1cf68743862049482406f2a49adbfb707..ca3a20d772ac7f6f8c1afe4e0ff4f90bfe7e75bc 100644 (file)
@@ -76,4 +76,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_LL                  46
+
 #endif /* __ASM_GENERIC_SOCKET_H */
index 788c0da5eed17fedee804c1654bff2b33d7d0261..1e744b12fda35364990e927b911b3ba2b615ade9 100644 (file)
@@ -913,6 +913,19 @@ set_rcvbuf:
                sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
                break;
 
+#ifdef CONFIG_NET_LL_RX_POLL
+       case SO_LL:
+               /* allow unprivileged users to decrease the value */
+               if ((val > sk->sk_ll_usec) && !capable(CAP_NET_ADMIN))
+                       ret = -EPERM;
+               else {
+                       if (val < 0)
+                               ret = -EINVAL;
+                       else
+                               sk->sk_ll_usec = val;
+               }
+               break;
+#endif
        default:
                ret = -ENOPROTOOPT;
                break;
@@ -1170,6 +1183,12 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
                break;
 
+#ifdef CONFIG_NET_LL_RX_POLL
+       case SO_LL:
+               v.val = sk->sk_ll_usec;
+               break;
+#endif
+
        default:
                return -ENOPROTOOPT;
        }
@@ -2288,6 +2307,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 
 #ifdef CONFIG_NET_LL_RX_POLL
        sk->sk_napi_id          =       0;
+       sk->sk_ll_usec          =       sysctl_net_ll_poll;
 #endif
 
        /*
index caaffa14e87e88260c14d6daaa0afb262b831c2e..3eec3f76b49c5a8b9035430463231fa7a72a660c 100644 (file)
 
 #ifdef CONFIG_NET_LL_RX_POLL
 unsigned int sysctl_net_ll_poll __read_mostly;
-EXPORT_SYMBOL_GPL(sysctl_net_ll_poll);
 #endif
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);