summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-04-20 20:04:01 +0200
committerDavid S. Miller <davem@davemloft.net>2012-04-21 16:24:20 -0400
commita74e910618efb154936958cfeb2aab7c234478c5 (patch)
treeeda84fcc25b12194b82c14786380121dbf86ec00
parentb139ba4e90dccbf4cd4efb112af96a5c9e0b098c (diff)
downloadlinux-3.10-a74e910618efb154936958cfeb2aab7c234478c5.tar.gz
linux-3.10-a74e910618efb154936958cfeb2aab7c234478c5.tar.bz2
linux-3.10-a74e910618efb154936958cfeb2aab7c234478c5.zip
net: change big iov allocations
iov of more than 8 entries are allocated in sendmsg()/recvmsg() through sock_kmalloc() As these allocations are temporary only and small enough, it makes sense to use plain kmalloc() and avoid sk_omem_alloc atomic overhead. Slightly changed fast path to be even faster. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Mike Waychison <mikew@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/socket.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/net/socket.c b/net/socket.c
index e34510928dc..d3aaa4f67a3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1908,7 +1908,7 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
__attribute__ ((aligned(sizeof(__kernel_size_t))));
/* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl;
- int err, ctl_len, iov_size, total_len;
+ int err, ctl_len, total_len;
err = -EFAULT;
if (MSG_CMSG_COMPAT & flags) {
@@ -1917,16 +1917,13 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
return -EFAULT;
- /* do not move before msg_sys is valid */
- err = -EMSGSIZE;
- if (msg_sys->msg_iovlen > UIO_MAXIOV)
- goto out;
-
- /* Check whether to allocate the iovec area */
- err = -ENOMEM;
- iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
if (msg_sys->msg_iovlen > UIO_FASTIOV) {
- iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+ err = -EMSGSIZE;
+ if (msg_sys->msg_iovlen > UIO_MAXIOV)
+ goto out;
+ err = -ENOMEM;
+ iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
+ GFP_KERNEL);
if (!iov)
goto out;
}
@@ -2005,7 +2002,7 @@ out_freectl:
sock_kfree_s(sock->sk, ctl_buf, ctl_len);
out_freeiov:
if (iov != iovstack)
- sock_kfree_s(sock->sk, iov, iov_size);
+ kfree(iov);
out:
return err;
}
@@ -2103,7 +2100,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack;
unsigned long cmsg_ptr;
- int err, iov_size, total_len, len;
+ int err, total_len, len;
/* kernel mode address */
struct sockaddr_storage addr;
@@ -2118,15 +2115,13 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
return -EFAULT;
- err = -EMSGSIZE;
- if (msg_sys->msg_iovlen > UIO_MAXIOV)
- goto out;
-
- /* Check whether to allocate the iovec area */
- err = -ENOMEM;
- iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
if (msg_sys->msg_iovlen > UIO_FASTIOV) {
- iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+ err = -EMSGSIZE;
+ if (msg_sys->msg_iovlen > UIO_MAXIOV)
+ goto out;
+ err = -ENOMEM;
+ iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
+ GFP_KERNEL);
if (!iov)
goto out;
}
@@ -2180,7 +2175,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
out_freeiov:
if (iov != iovstack)
- sock_kfree_s(sock->sk, iov, iov_size);
+ kfree(iov);
out:
return err;
}