Commit a74e9106 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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: default avatarEric Dumazet <edumazet@google.com>
Cc: Mike Waychison <mikew@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b139ba4e
...@@ -1908,7 +1908,7 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, ...@@ -1908,7 +1908,7 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
__attribute__ ((aligned(sizeof(__kernel_size_t)))); __attribute__ ((aligned(sizeof(__kernel_size_t))));
/* 20 is size of ipv6_pktinfo */ /* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl; unsigned char *ctl_buf = ctl;
int err, ctl_len, iov_size, total_len; int err, ctl_len, total_len;
err = -EFAULT; err = -EFAULT;
if (MSG_CMSG_COMPAT & flags) { if (MSG_CMSG_COMPAT & flags) {
...@@ -1917,16 +1917,13 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, ...@@ -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))) } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
return -EFAULT; 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) { 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) if (!iov)
goto out; goto out;
} }
...@@ -2005,7 +2002,7 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, ...@@ -2005,7 +2002,7 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
sock_kfree_s(sock->sk, ctl_buf, ctl_len); sock_kfree_s(sock->sk, ctl_buf, ctl_len);
out_freeiov: out_freeiov:
if (iov != iovstack) if (iov != iovstack)
sock_kfree_s(sock->sk, iov, iov_size); kfree(iov);
out: out:
return err; return err;
} }
...@@ -2103,7 +2100,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, ...@@ -2103,7 +2100,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack; struct iovec *iov = iovstack;
unsigned long cmsg_ptr; unsigned long cmsg_ptr;
int err, iov_size, total_len, len; int err, total_len, len;
/* kernel mode address */ /* kernel mode address */
struct sockaddr_storage addr; struct sockaddr_storage addr;
...@@ -2118,15 +2115,13 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, ...@@ -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))) } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
return -EFAULT; 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) { 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) if (!iov)
goto out; goto out;
} }
...@@ -2180,7 +2175,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, ...@@ -2180,7 +2175,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
out_freeiov: out_freeiov:
if (iov != iovstack) if (iov != iovstack)
sock_kfree_s(sock->sk, iov, iov_size); kfree(iov);
out: out:
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment