Line data Source code
1 : #include <linux/uaccess.h>
2 : #include <linux/export.h>
3 : #include <linux/uio.h>
4 :
5 : /*
6 : * Copy iovec to kernel. Returns -EFAULT on error.
7 : *
8 : * Note: this modifies the original iovec.
9 : */
10 :
11 715 : int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
12 : {
13 2677 : while (len > 0) {
14 1247 : if (iov->iov_len) {
15 1247 : int copy = min_t(unsigned int, len, iov->iov_len);
16 2494 : if (copy_from_user(kdata, iov->iov_base, copy))
17 : return -EFAULT;
18 1247 : len -= copy;
19 1247 : kdata += copy;
20 1247 : iov->iov_base += copy;
21 1247 : iov->iov_len -= copy;
22 : }
23 1247 : iov++;
24 : }
25 :
26 : return 0;
27 : }
28 : EXPORT_SYMBOL(memcpy_fromiovec);
29 :
30 : /*
31 : * Copy kernel to iovec. Returns -EFAULT on error.
32 : */
33 :
34 0 : int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata,
35 : int offset, int len)
36 : {
37 : int copy;
38 0 : for (; len > 0; ++iov) {
39 : /* Skip over the finished iovecs */
40 0 : if (unlikely(offset >= iov->iov_len)) {
41 0 : offset -= iov->iov_len;
42 0 : continue;
43 : }
44 0 : copy = min_t(unsigned int, iov->iov_len - offset, len);
45 0 : if (copy_to_user(iov->iov_base + offset, kdata, copy))
46 : return -EFAULT;
47 : offset = 0;
48 0 : kdata += copy;
49 0 : len -= copy;
50 : }
51 :
52 : return 0;
53 : }
54 : EXPORT_SYMBOL(memcpy_toiovecend);
55 :
56 : /*
57 : * Copy iovec to kernel. Returns -EFAULT on error.
58 : */
59 :
60 320 : int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
61 : int offset, int len)
62 : {
63 : /* No data? Done! */
64 320 : if (len == 0)
65 : return 0;
66 :
67 : /* Skip over the finished iovecs */
68 320 : while (offset >= iov->iov_len) {
69 0 : offset -= iov->iov_len;
70 0 : iov++;
71 : }
72 :
73 640 : while (len > 0) {
74 320 : u8 __user *base = iov->iov_base + offset;
75 320 : int copy = min_t(unsigned int, len, iov->iov_len - offset);
76 :
77 : offset = 0;
78 320 : if (copy_from_user(kdata, base, copy))
79 : return -EFAULT;
80 320 : len -= copy;
81 320 : kdata += copy;
82 320 : iov++;
83 : }
84 :
85 : return 0;
86 : }
87 : EXPORT_SYMBOL(memcpy_fromiovecend);
|