|
@@ -568,6 +568,31 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(copy_from_iter);
|
|
EXPORT_SYMBOL(copy_from_iter);
|
|
|
|
|
|
|
|
+bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
|
|
|
|
+{
|
|
|
|
+ char *to = addr;
|
|
|
|
+ if (unlikely(i->type & ITER_PIPE)) {
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (unlikely(i->count < bytes)) \
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ iterate_all_kinds(i, bytes, v, ({
|
|
|
|
+ if (__copy_from_user((to += v.iov_len) - v.iov_len,
|
|
|
|
+ v.iov_base, v.iov_len))
|
|
|
|
+ return false;
|
|
|
|
+ 0;}),
|
|
|
|
+ memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page,
|
|
|
|
+ v.bv_offset, v.bv_len),
|
|
|
|
+ memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len)
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ iov_iter_advance(i, bytes);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(copy_from_iter_full);
|
|
|
|
+
|
|
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
|
|
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
|
|
{
|
|
{
|
|
char *to = addr;
|
|
char *to = addr;
|
|
@@ -587,6 +612,30 @@ size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(copy_from_iter_nocache);
|
|
EXPORT_SYMBOL(copy_from_iter_nocache);
|
|
|
|
|
|
|
|
+bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
|
|
|
|
+{
|
|
|
|
+ char *to = addr;
|
|
|
|
+ if (unlikely(i->type & ITER_PIPE)) {
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (unlikely(i->count < bytes)) \
|
|
|
|
+ return false;
|
|
|
|
+ iterate_all_kinds(i, bytes, v, ({
|
|
|
|
+ if (__copy_from_user_nocache((to += v.iov_len) - v.iov_len,
|
|
|
|
+ v.iov_base, v.iov_len))
|
|
|
|
+ return false;
|
|
|
|
+ 0;}),
|
|
|
|
+ memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page,
|
|
|
|
+ v.bv_offset, v.bv_len),
|
|
|
|
+ memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len)
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ iov_iter_advance(i, bytes);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(copy_from_iter_full_nocache);
|
|
|
|
+
|
|
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
|
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
|
struct iov_iter *i)
|
|
struct iov_iter *i)
|
|
{
|
|
{
|
|
@@ -1008,7 +1057,7 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
|
|
}
|
|
}
|
|
iterate_and_advance(i, bytes, v, ({
|
|
iterate_and_advance(i, bytes, v, ({
|
|
int err = 0;
|
|
int err = 0;
|
|
- next = csum_and_copy_from_user(v.iov_base,
|
|
|
|
|
|
+ next = csum_and_copy_from_user(v.iov_base,
|
|
(to += v.iov_len) - v.iov_len,
|
|
(to += v.iov_len) - v.iov_len,
|
|
v.iov_len, 0, &err);
|
|
v.iov_len, 0, &err);
|
|
if (!err) {
|
|
if (!err) {
|
|
@@ -1037,6 +1086,51 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(csum_and_copy_from_iter);
|
|
EXPORT_SYMBOL(csum_and_copy_from_iter);
|
|
|
|
|
|
|
|
+bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum,
|
|
|
|
+ struct iov_iter *i)
|
|
|
|
+{
|
|
|
|
+ char *to = addr;
|
|
|
|
+ __wsum sum, next;
|
|
|
|
+ size_t off = 0;
|
|
|
|
+ sum = *csum;
|
|
|
|
+ if (unlikely(i->type & ITER_PIPE)) {
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (unlikely(i->count < bytes))
|
|
|
|
+ return false;
|
|
|
|
+ iterate_all_kinds(i, bytes, v, ({
|
|
|
|
+ int err = 0;
|
|
|
|
+ next = csum_and_copy_from_user(v.iov_base,
|
|
|
|
+ (to += v.iov_len) - v.iov_len,
|
|
|
|
+ v.iov_len, 0, &err);
|
|
|
|
+ if (err)
|
|
|
|
+ return false;
|
|
|
|
+ sum = csum_block_add(sum, next, off);
|
|
|
|
+ off += v.iov_len;
|
|
|
|
+ 0;
|
|
|
|
+ }), ({
|
|
|
|
+ char *p = kmap_atomic(v.bv_page);
|
|
|
|
+ next = csum_partial_copy_nocheck(p + v.bv_offset,
|
|
|
|
+ (to += v.bv_len) - v.bv_len,
|
|
|
|
+ v.bv_len, 0);
|
|
|
|
+ kunmap_atomic(p);
|
|
|
|
+ sum = csum_block_add(sum, next, off);
|
|
|
|
+ off += v.bv_len;
|
|
|
|
+ }),({
|
|
|
|
+ next = csum_partial_copy_nocheck(v.iov_base,
|
|
|
|
+ (to += v.iov_len) - v.iov_len,
|
|
|
|
+ v.iov_len, 0);
|
|
|
|
+ sum = csum_block_add(sum, next, off);
|
|
|
|
+ off += v.iov_len;
|
|
|
|
+ })
|
|
|
|
+ )
|
|
|
|
+ *csum = sum;
|
|
|
|
+ iov_iter_advance(i, bytes);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(csum_and_copy_from_iter_full);
|
|
|
|
+
|
|
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
|
|
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
|
|
struct iov_iter *i)
|
|
struct iov_iter *i)
|
|
{
|
|
{
|
|
@@ -1051,7 +1145,7 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
|
|
iterate_and_advance(i, bytes, v, ({
|
|
iterate_and_advance(i, bytes, v, ({
|
|
int err = 0;
|
|
int err = 0;
|
|
next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len,
|
|
next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len,
|
|
- v.iov_base,
|
|
|
|
|
|
+ v.iov_base,
|
|
v.iov_len, 0, &err);
|
|
v.iov_len, 0, &err);
|
|
if (!err) {
|
|
if (!err) {
|
|
sum = csum_block_add(sum, next, off);
|
|
sum = csum_block_add(sum, next, off);
|