patch-2.1.68 linux/net/core/iovec.c
Next file: linux/net/core/net_alias.c
Previous file: linux/net/core/dev_mcast.c
Back to the patch index
Back to the overall index
- Lines: 140
- Date:
Sun Nov 30 14:00:39 1997
- Orig file:
v2.1.67/linux/net/core/iovec.c
- Orig date:
Sun Feb 2 05:18:49 1997
diff -u --recursive --new-file v2.1.67/linux/net/core/iovec.c linux/net/core/iovec.c
@@ -192,69 +192,78 @@
*
* ip_build_xmit must ensure that when fragmenting only the last
* call to this function will be unaligned also.
- *
- * FIXME: add an error handling path when a copy/checksum from
- * user space failed because of a invalid pointer.
*/
-unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata,
- struct iovec *iov, int offset,
- int len, int csum)
+int csum_partial_copy_fromiovecend(unsigned char *kdata,
+ struct iovec *iov, int offset,
+ int len, int *csump)
{
- __u32 partial;
- __u32 partial_cnt = 0;
-
- while(offset>0)
- {
- if (offset > iov->iov_len)
- {
- offset -= iov->iov_len;
-
- }
- else
- {
- u8 *base;
- int copy;
-
- base = iov->iov_base + offset;
- copy = min(len, iov->iov_len - offset);
- offset = 0;
+ int partial_cnt = 0;
+ int err = 0;
+ int csum;
+
+ 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_partial_copy_from_user(base, kdata,
+ len, *csump, &err);
+ return err;
+ }
partial_cnt = copy % 4;
- if (partial_cnt)
- {
+ if (partial_cnt) {
copy -= partial_cnt;
- copy_from_user(&partial, base + copy,
- partial_cnt);
+ err |= copy_from_user(kdata+copy, base+copy, partial_cnt);
}
- /*
- * FIXME: add exception handling to the
- * csum functions and set *err when an
- * exception occurs.
- */
- csum = csum_partial_copy_fromuser(base, kdata,
- copy, csum);
+ *csump = csum_partial_copy_from_user(base, kdata,
+ copy, *csump, &err);
len -= copy + partial_cnt;
kdata += copy + partial_cnt;
+ iov++;
+ break;
}
- iov++;
- }
+ iov++;
+ offset = -copy;
+ } while (offset > 0);
+
+ csum = *csump;
while (len>0)
{
u8 *base = iov->iov_base;
- int copy=min(len, iov->iov_len);
+ int copy = min(len, iov->iov_len);
+ /* There is a remnant from previous iov. */
if (partial_cnt)
{
int par_len = 4 - partial_cnt;
- copy_from_user(&partial, base + partial_cnt, par_len);
- csum = csum_partial((u8*) &partial, 4, csum);
+ /* iov component is too short ... */
+ if (par_len > copy) {
+ err |= copy_from_user(kdata, base, copy);
+ base += copy;
+ partial_cnt += copy;
+ kdata += copy;
+ len -= copy;
+ iov++;
+ if (len)
+ continue;
+ *csump = csum_partial(kdata-partial_cnt, partial_cnt, csum);
+ return err;
+ }
+ err |= copy_from_user(kdata, base, par_len);
+ csum = csum_partial(kdata-partial_cnt, 4, csum);
base += par_len;
copy -= par_len;
+ len -= par_len;
+ kdata += par_len;
partial_cnt = 0;
}
@@ -264,16 +273,15 @@
if (partial_cnt)
{
copy -= partial_cnt;
- copy_from_user(&partial, base + copy,
- partial_cnt);
+ err |= copy_from_user(kdata+copy, base + copy, partial_cnt);
}
}
- csum = csum_partial_copy_fromuser(base, kdata, copy, csum);
+ csum = csum_partial_copy_from_user(base, kdata, copy, csum, &err);
len -= copy + partial_cnt;
kdata += copy + partial_cnt;
iov++;
}
-
- return csum;
+ *csump = csum;
+ return err;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov