diff options
author | Eric Dumazet <edumazet@google.com> | 2012-04-20 14:04:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-21 16:24:20 -0400 |
commit | a74e910618efb154936958cfeb2aab7c234478c5 (patch) | |
tree | eda84fcc25b12194b82c14786380121dbf86ec00 /net/socket.c | |
parent | b139ba4e90dccbf4cd4efb112af96a5c9e0b098c (diff) |
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>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/net/socket.c b/net/socket.c index e34510928dcc..d3aaa4f67a3b 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1908,7 +1908,7 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | |||
1908 | __attribute__ ((aligned(sizeof(__kernel_size_t)))); | 1908 | __attribute__ ((aligned(sizeof(__kernel_size_t)))); |
1909 | /* 20 is size of ipv6_pktinfo */ | 1909 | /* 20 is size of ipv6_pktinfo */ |
1910 | unsigned char *ctl_buf = ctl; | 1910 | unsigned char *ctl_buf = ctl; |
1911 | int err, ctl_len, iov_size, total_len; | 1911 | int err, ctl_len, total_len; |
1912 | 1912 | ||
1913 | err = -EFAULT; | 1913 | err = -EFAULT; |
1914 | if (MSG_CMSG_COMPAT & flags) { | 1914 | if (MSG_CMSG_COMPAT & flags) { |
@@ -1917,16 +1917,13 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | |||
1917 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) | 1917 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) |
1918 | return -EFAULT; | 1918 | return -EFAULT; |
1919 | 1919 | ||
1920 | /* do not move before msg_sys is valid */ | ||
1921 | err = -EMSGSIZE; | ||
1922 | if (msg_sys->msg_iovlen > UIO_MAXIOV) | ||
1923 | goto out; | ||
1924 | |||
1925 | /* Check whether to allocate the iovec area */ | ||
1926 | err = -ENOMEM; | ||
1927 | iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); | ||
1928 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { | 1920 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { |
1929 | iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); | 1921 | err = -EMSGSIZE; |
1922 | if (msg_sys->msg_iovlen > UIO_MAXIOV) | ||
1923 | goto out; | ||
1924 | err = -ENOMEM; | ||
1925 | iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec), | ||
1926 | GFP_KERNEL); | ||
1930 | if (!iov) | 1927 | if (!iov) |
1931 | goto out; | 1928 | goto out; |
1932 | } | 1929 | } |
@@ -2005,7 +2002,7 @@ out_freectl: | |||
2005 | sock_kfree_s(sock->sk, ctl_buf, ctl_len); | 2002 | sock_kfree_s(sock->sk, ctl_buf, ctl_len); |
2006 | out_freeiov: | 2003 | out_freeiov: |
2007 | if (iov != iovstack) | 2004 | if (iov != iovstack) |
2008 | sock_kfree_s(sock->sk, iov, iov_size); | 2005 | kfree(iov); |
2009 | out: | 2006 | out: |
2010 | return err; | 2007 | return err; |
2011 | } | 2008 | } |
@@ -2103,7 +2100,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | |||
2103 | struct iovec iovstack[UIO_FASTIOV]; | 2100 | struct iovec iovstack[UIO_FASTIOV]; |
2104 | struct iovec *iov = iovstack; | 2101 | struct iovec *iov = iovstack; |
2105 | unsigned long cmsg_ptr; | 2102 | unsigned long cmsg_ptr; |
2106 | int err, iov_size, total_len, len; | 2103 | int err, total_len, len; |
2107 | 2104 | ||
2108 | /* kernel mode address */ | 2105 | /* kernel mode address */ |
2109 | struct sockaddr_storage addr; | 2106 | struct sockaddr_storage addr; |
@@ -2118,15 +2115,13 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | |||
2118 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) | 2115 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) |
2119 | return -EFAULT; | 2116 | return -EFAULT; |
2120 | 2117 | ||
2121 | err = -EMSGSIZE; | ||
2122 | if (msg_sys->msg_iovlen > UIO_MAXIOV) | ||
2123 | goto out; | ||
2124 | |||
2125 | /* Check whether to allocate the iovec area */ | ||
2126 | err = -ENOMEM; | ||
2127 | iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); | ||
2128 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { | 2118 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { |
2129 | iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); | 2119 | err = -EMSGSIZE; |
2120 | if (msg_sys->msg_iovlen > UIO_MAXIOV) | ||
2121 | goto out; | ||
2122 | err = -ENOMEM; | ||
2123 | iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec), | ||
2124 | GFP_KERNEL); | ||
2130 | if (!iov) | 2125 | if (!iov) |
2131 | goto out; | 2126 | goto out; |
2132 | } | 2127 | } |
@@ -2180,7 +2175,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | |||
2180 | 2175 | ||
2181 | out_freeiov: | 2176 | out_freeiov: |
2182 | if (iov != iovstack) | 2177 | if (iov != iovstack) |
2183 | sock_kfree_s(sock->sk, iov, iov_size); | 2178 | kfree(iov); |
2184 | out: | 2179 | out: |
2185 | return err; | 2180 | return err; |
2186 | } | 2181 | } |