From: Simon Wilkinson Date: Fri, 23 Apr 2010 17:03:49 +0000 (+0100) Subject: Linux: Use kernel network helper functions X-Git-Tag: openafs-devel-1_5_75~373 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=1798fe6da1d40c083bc10fe101a73b5f67b6fa0d;p=packages%2Fo%2Fopenafs.git Linux: Use kernel network helper functions 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 Tested-by: Derrick Brashear --- diff --git a/acinclude.m4 b/acinclude.m4 index 14f10e837..88be3f559 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h index e507e6b45..efdd13b21 100644 --- a/src/afs/LINUX/osi_compat.h +++ b/src/afs/LINUX/osi_compat.h @@ -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 + diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4 index 8d0a00fce..e442ee1a5 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -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 ], +[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]) + diff --git a/src/rx/LINUX/rx_knet.c b/src/rx/LINUX/rx_knet.c index d670a833f..bfe7c078b 100644 --- a/src/rx/LINUX/rx_knet.c +++ b/src/rx/LINUX/rx_knet.c @@ -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 (