summaryrefslogtreecommitdiffstats
path: root/net/core/iovec.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-04-05 11:23:36 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-04-05 11:23:36 +0000
commit4318fbda2a7ee51caafdc4eb1f8028a3f0605142 (patch)
treecddb50a81d7d1a628cc400519162080c6d87868e /net/core/iovec.c
parent36ea5120664550fae6d31f1c6f695e4f8975cb06 (diff)
o Merge with Linux 2.1.91.
o First round of bugfixes for the SC/MC CPUs. o FPU context switch fixes. o Lazy context switches. o Faster syscalls. o Removed dead code. o Shitloads of other things I forgot ...
Diffstat (limited to 'net/core/iovec.c')
-rw-r--r--net/core/iovec.c91
1 files changed, 24 insertions, 67 deletions
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 9e8873646..5b684a48f 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -30,7 +30,6 @@
/*
* 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.
@@ -79,22 +78,21 @@ out_free:
}
/*
- * Copy kernel to iovec.
+ * Copy kernel to iovec. Returns -EFAULT on error.
*
* Note: this modifies the original iovec.
*/
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
{
- int err;
+ int err = -EFAULT;
while(len>0)
{
if(iov->iov_len)
{
int copy = min(iov->iov_len, len);
- err = copy_to_user(iov->iov_base, kdata, copy);
- if (err)
+ if (copy_to_user(iov->iov_base, kdata, copy))
goto out;
kdata+=copy;
len-=copy;
@@ -109,7 +107,7 @@ out:
}
/*
- * Copy iovec to kernel.
+ * Copy iovec to kernel. Returns -EFAULT on error.
*
* Note: this modifies the original iovec.
*/
@@ -147,35 +145,23 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
{
int err = -EFAULT;
- while(offset>0)
+ /* Skip over the finished iovecs */
+ while(offset >= iov->iov_len)
{
- if (offset > iov->iov_len)
- {
- offset -= iov->iov_len;
- }
- else
- {
- u8 *base = iov->iov_base + offset;
- int copy = min(len, iov->iov_len - offset);
-
- offset = 0;
-
- if (copy_from_user(kdata, base, copy))
- goto out;
- len-=copy;
- kdata+=copy;
- }
+ offset -= iov->iov_len;
iov++;
}
- while (len>0)
+ while (len > 0)
{
- int copy = min(len, iov->iov_len);
+ u8 *base = iov->iov_base + offset;
+ int copy = min(len, iov->iov_len - offset);
- if (copy_from_user(kdata, iov->iov_base, copy))
+ offset = 0;
+ if (copy_from_user(kdata, base, copy))
goto out;
- len-=copy;
- kdata+=copy;
+ len -= copy;
+ kdata += copy;
iov++;
}
err = 0;
@@ -195,51 +181,22 @@ out:
int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
int offset, unsigned int len, int *csump)
{
- int partial_cnt = 0;
- int err = 0;
- int csum;
+ int csum = *csump;
+ int partial_cnt = 0, err = 0;
- do {
- int copy = iov->iov_len - offset;
-
- if (copy > 0) {
- u8 *base = iov->iov_base + offset;
-
- /* Normal case (single iov component) is fastly detected */
- if (len <= copy) {
- *csump = csum_and_copy_from_user(base, kdata,
- len, *csump, &err);
- goto out;
- }
-
- partial_cnt = copy % 4;
- if (partial_cnt) {
- copy -= partial_cnt;
- if (copy_from_user(kdata + copy, base + copy,
- partial_cnt))
- goto out_fault;
- }
-
- *csump = csum_and_copy_from_user(base, kdata, copy,
- *csump, &err);
- if (err)
- goto out;
- len -= copy + partial_cnt;
- kdata += copy + partial_cnt;
- iov++;
- break;
- }
+ /* Skip over the finished iovecs */
+ while (offset >= iov->iov_len)
+ {
+ offset -= iov->iov_len;
iov++;
- offset = -copy;
- } while (offset > 0);
-
- csum = *csump;
+ }
while (len > 0)
{
- u8 *base = iov->iov_base;
- unsigned int copy = min(len, iov->iov_len);
+ u8 *base = iov->iov_base + offset;
+ unsigned int copy = min(len, iov->iov_len - offset);
+ offset = 0;
/* There is a remnant from previous iov. */
if (partial_cnt)
{