summaryrefslogtreecommitdiffstats
path: root/net/core/iovec.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/iovec.c')
-rw-r--r--net/core/iovec.c55
1 files changed, 28 insertions, 27 deletions
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 6db6ac3e9..9bc21ffc5 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -11,7 +11,8 @@
* Andrew Lunn : Errors in iovec copying.
* Pedro Roque : Added memcpy_fromiovecend and
* csum_..._fromiovecend.
- * Andi Kleen : fixed error handling for 2.1
+ * Andi Kleen : fixed error handling for 2.1
+ * Alexey Kuznetsov: 2.1 optimisations
*/
@@ -19,6 +20,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/malloc.h>
#include <linux/net.h>
#include <linux/in6.h>
#include <asm/uaccess.h>
@@ -34,6 +36,9 @@ extern inline int min(int x, int y)
/*
* Verify iovec
* verify area does a simple check for completly bogus addresses
+ *
+ * Save time not doing verify_area. copy_*_user will make this work
+ * in any case.
*/
int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
@@ -42,42 +47,38 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
int len=0;
int ct;
- if(m->msg_name!=NULL)
+ if(m->msg_namelen)
{
if(mode==VERIFY_READ)
{
err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
- }
- else
- {
- err=verify_area(mode, m->msg_name, m->msg_namelen);
+ if(err<0)
+ return err;
}
- if(err<0)
- return err;
m->msg_name = address;
+ } else
+ m->msg_name = NULL;
+
+ if (m->msg_iovlen > UIO_FASTIOV)
+ {
+ iov = kmalloc(m->msg_iovlen*sizeof(struct iovec), GFP_KERNEL);
+ if (!iov)
+ return -ENOMEM;
}
- if(m->msg_control!=NULL)
+ err = copy_from_user(iov, m->msg_iov, sizeof(struct iovec)*m->msg_iovlen);
+ if (err)
{
- err=verify_area(mode, m->msg_control, m->msg_controllen);
- if(err)
- return err;
+ if (m->msg_iovlen > UIO_FASTIOV)
+ kfree(iov);
+ return -EFAULT;
}
-
+
for(ct=0;ct<m->msg_iovlen;ct++)
- {
- err = copy_from_user(&iov[ct], &m->msg_iov[ct],
- sizeof(struct iovec));
- if (err)
- return err;
-
- err = verify_area(mode, iov[ct].iov_base, iov[ct].iov_len);
- if(err)
- return err;
len+=iov[ct].iov_len;
- }
- m->msg_iov=&iov[0];
+
+ m->msg_iov=iov;
return len;
}
@@ -121,7 +122,7 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
err = copy_from_user(kdata, iov->iov_base, copy);
if (err)
{
- return err;
+ return -EFAULT;
}
len-=copy;
kdata+=copy;
@@ -161,7 +162,7 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
err = copy_from_user(kdata, base, copy);
if (err)
{
- return err;
+ return -EFAULT;
}
len-=copy;
kdata+=copy;
@@ -175,7 +176,7 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
err = copy_from_user(kdata, iov->iov_base, copy);
if (err)
{
- return err;
+ return -EFAULT;
}
len-=copy;
kdata+=copy;