]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Linux: Use kernel network helper functions
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Fri, 23 Apr 2010 17:03:49 +0000 (18:03 +0100)
committerDerrick Brashear <shadow@dementia.org>
Mon, 26 Apr 2010 04:09:20 +0000 (21:09 -0700)
Linux has various network helper functions available, which are
guaranteed to do the right thing in terms of setting address space
limits, not dereferencing NULL pointers, and the like. Use these, where
they're available, rather than rolling our own.

kernel_sendmsg and kernel_recvmsg appeared in 2.6.8.

Change-Id: I1cd91afd2182ad936756bbc4cf692262499c16e4
Reviewed-on: http://gerrit.openafs.org/1822
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
acinclude.m4
src/afs/LINUX/osi_compat.h
src/cf/linux-test4.m4
src/rx/LINUX/rx_knet.c

index 14f10e837afc39f927bf8b3fbfd73fc6d438d822..88be3f559e5937b115757de0b7620566de4f1dfa 100644 (file)
@@ -816,6 +816,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_HAVE_PAGE_OFFSET
                 LINUX_HAVE_ZERO_USER_SEGMENTS
                 LINUX_HAVE_VFS_LLSEEK
+                LINUX_HAVE_KERNEL_SETSOCKOPT
                  LINUX_STRUCT_TASK_HAS_CRED
                 LINUX_STRUCT_PROC_DIR_ENTRY_HAS_OWNER
                 LINUX_HAVE_KMEM_CACHE_T
index e507e6b45e4cc9cdb9f6dde165d2084b45d22456..efdd13b219098b363f30f5143c234ef90b2d0878 100644 (file)
@@ -239,3 +239,34 @@ vfs_llseek(struct file *filp, loff_t offset, int origin) {
 }
 #endif
 
+#ifndef HAVE_KERNEL_SETSOCKOPT
+/* Available from 2.6.19 */
+
+static inline int
+kernel_setsockopt(struct socket *sockp, int level, int name, char *val,
+                 unsigned int len) {
+    mm_segment_t old_fs = get_fs();
+    int ret;
+
+    set_fs(get_ds());
+    ret = sockp->ops->setsockopt(sockp, level, name, val, len);
+    set_fs(old_fs);
+
+    return ret;
+}
+
+static inline int
+kernel_getsockopt(struct socket *sockp, int level, int name, char *val,
+                 int *len) {
+    mm_segment_t old_fs = get_fs();
+    int ret;
+
+    set_fs(get_ds());
+    ret = sockp->ops->setsockopt(sockp, level, name, val, len);
+    set_fs(old_fs);
+
+    return ret;
+}
+
+#endif
+
index 8d0a00fceacbd97b56bf7410ca65310c185efd8c..e442ee1a5cf50f493296544afab0d16504468990 100644 (file)
@@ -1270,3 +1270,16 @@ AC_DEFUN([LINUX_HAVE_VFS_LLSEEK], [
     AC_DEFINE([HAVE_VFS_LLSEEK], 1, [define if your kernel has the vfs_llseek function])
   fi])
 
+AC_DEFUN([LINUX_HAVE_KERNEL_SETSOCKOPT], [
+  AC_MSG_CHECKING([for kernel_setsockopt])
+  AC_CACHE_VAL([ac_cv_linux_have_kernel_setsockopt], [
+    AC_TRY_KBUILD(
+[#include <linux/net.h>],
+[kernel_setsockopt(NULL, 0, 0, NULL, 0);],
+      ac_cv_linux_have_kernel_setsockopt=yes,
+      ac_cv_linux_have_kernel_setsockopt=no)])
+  AC_MSG_RESULT($ac_cv_linux_have_kernel_setsockopt)
+  if test "x$ac_cv_linux_have_kernel_setsockopt" = "xyes"; then
+    AC_DEFINE([HAVE_KERNEL_SETSOCKOPT], 1, [define if your kernel has the kernel_setsockopt function])
+  fi])
+
index d670a833fbc4d82e20f5c98d114b7431996fa425..bfe7c078b804d0fa083fd85280a4bc8a46f3b7ed 100644 (file)
@@ -34,7 +34,6 @@ rxk_NewSocketHost(afs_uint32 ahost, short aport)
     struct socket *sockp;
     struct sockaddr_in myaddr;
     int code;
-    KERNEL_SPACE_DECL;
 #ifdef ADAPT_PMTU
     int pmtu = IP_PMTUDISC_WANT;
     int do_recverr = 1;
@@ -65,14 +64,12 @@ rxk_NewSocketHost(afs_uint32 ahost, short aport)
        return NULL;
     }
 
-    TO_USER_SPACE();
-    sockp->ops->setsockopt(sockp, SOL_IP, IP_MTU_DISCOVER, (char *)&pmtu,
-                           sizeof(pmtu));
+    kernel_setsockopt(sockp, SOL_IP, IP_MTU_DISCOVER, (char *)&pmtu,
+                     sizeof(pmtu));
 #ifdef ADAPT_PMTU
-    sockp->ops->setsockopt(sockp, SOL_IP, IP_RECVERR, (char *)&do_recverr,
-                           sizeof(do_recverr));
+    kernel_setsockopt(sockp, SOL_IP, IP_RECVERR, (char *)&do_recverr,
+                      sizeof(do_recverr));
 #endif
-    TO_KERNEL_SPACE();
     return (osi_socket *)sockp;
 }
 
@@ -94,7 +91,6 @@ rxk_FreeSocket(struct socket *asocket)
 void
 handle_socket_error(osi_socket so)
 {
-    KERNEL_SPACE_DECL;
     struct msghdr msg;
     struct cmsghdr *cmsg;
     struct sock_extended_err *err;
@@ -108,15 +104,12 @@ handle_socket_error(osi_socket so)
        return;
     msg.msg_name = &addr;
     msg.msg_namelen = sizeof(addr);
-    msg.msg_iov = NULL;
-    msg.msg_iovlen = 0;
     msg.msg_control = controlmsgbuf;
     msg.msg_controllen = 256;
     msg.msg_flags = 0;
 
-    TO_USER_SPACE();
-    code = sock_recvmsg(sop, &msg, 256, MSG_ERRQUEUE|MSG_DONTWAIT|MSG_TRUNC);
-    TO_KERNEL_SPACE();
+    code = kernel_recvmsg(sop, &msg, NULL, 0, 256,
+                         MSG_ERRQUEUE|MSG_DONTWAIT|MSG_TRUNC);
 
     if (code < 0 || !(msg.msg_flags & MSG_ERRQUEUE))
        goto out;
@@ -160,7 +153,6 @@ int
 osi_NetSend(osi_socket sop, struct sockaddr_in *to, struct iovec *iovec,
            int iovcnt, afs_int32 size, int istack)
 {
-    KERNEL_SPACE_DECL;
     struct msghdr msg;
     int code;
 #ifdef ADAPT_PMTU
@@ -170,27 +162,20 @@ osi_NetSend(osi_socket sop, struct sockaddr_in *to, struct iovec *iovec,
     while (1) {
        sockerr=0;
        esize = sizeof(sockerr);
-       TO_USER_SPACE();
-       sop->ops->getsockopt(sop, SOL_SOCKET, SO_ERROR, (char *)&sockerr,
-                          &esize);
-       TO_KERNEL_SPACE();
+       kernel_getsockopt(sop, SOL_SOCKET, SO_ERROR, (char *)&sockerr, &esize);
        if (sockerr == 0)
           break;
        handle_socket_error(sop);
     }
 #endif
 
-    msg.msg_iovlen = iovcnt;
-    msg.msg_iov = iovec;
     msg.msg_name = to;
     msg.msg_namelen = sizeof(*to);
     msg.msg_control = NULL;
     msg.msg_controllen = 0;
     msg.msg_flags = 0;
 
-    TO_USER_SPACE();
-    code = sock_sendmsg(sop, &msg, size);
-    TO_KERNEL_SPACE();
+    code = kernel_sendmsg(sop, &msg, (struct kvec *) iovec, iovcnt, size);
     return (code < 0) ? code : 0;
 }
 
@@ -220,7 +205,6 @@ int
 osi_NetReceive(osi_socket so, struct sockaddr_in *from, struct iovec *iov,
               int iovcnt, int *lengthp)
 {
-    KERNEL_SPACE_DECL;
     struct msghdr msg;
     int code;
 #ifdef ADAPT_PMTU
@@ -237,10 +221,7 @@ osi_NetReceive(osi_socket so, struct sockaddr_in *from, struct iovec *iov,
     while (1) {
        sockerr=0;
        esize = sizeof(sockerr);
-       TO_USER_SPACE();
-       sop->ops->getsockopt(sop, SOL_SOCKET, SO_ERROR, (char *)&sockerr,
-                          &esize);
-       TO_KERNEL_SPACE();
+       kernel_getsockopt(sop, SOL_SOCKET, SO_ERROR, (char *)&sockerr, &esize);
        if (sockerr == 0)
           break;
        handle_socket_error(so);
@@ -254,10 +235,8 @@ osi_NetReceive(osi_socket so, struct sockaddr_in *from, struct iovec *iov,
     msg.msg_controllen = 0;
     msg.msg_flags = 0;
 
-    TO_USER_SPACE();
-    code = sock_recvmsg(sop, &msg, *lengthp, 0);
-    TO_KERNEL_SPACE();
-
+    code = kernel_recvmsg(sop, &msg, (struct kvec *)tmpvec, iovcnt,
+                         *lengthp, 0);
     if (code < 0) {
 #ifdef CONFIG_PM
        if (