diff options
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r-- | lib/iov_iter.c | 98 |
1 files changed, 96 insertions, 2 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 691a52b634fe..228892dabba6 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -569,6 +569,31 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | |||
569 | } | 569 | } |
570 | EXPORT_SYMBOL(copy_from_iter); | 570 | EXPORT_SYMBOL(copy_from_iter); |
571 | 571 | ||
572 | bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) | ||
573 | { | ||
574 | char *to = addr; | ||
575 | if (unlikely(i->type & ITER_PIPE)) { | ||
576 | WARN_ON(1); | ||
577 | return false; | ||
578 | } | ||
579 | if (unlikely(i->count < bytes)) \ | ||
580 | return false; | ||
581 | |||
582 | iterate_all_kinds(i, bytes, v, ({ | ||
583 | if (__copy_from_user((to += v.iov_len) - v.iov_len, | ||
584 | v.iov_base, v.iov_len)) | ||
585 | return false; | ||
586 | 0;}), | ||
587 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, | ||
588 | v.bv_offset, v.bv_len), | ||
589 | memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) | ||
590 | ) | ||
591 | |||
592 | iov_iter_advance(i, bytes); | ||
593 | return true; | ||
594 | } | ||
595 | EXPORT_SYMBOL(copy_from_iter_full); | ||
596 | |||
572 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | 597 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) |
573 | { | 598 | { |
574 | char *to = addr; | 599 | char *to = addr; |
@@ -588,6 +613,30 @@ size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | |||
588 | } | 613 | } |
589 | EXPORT_SYMBOL(copy_from_iter_nocache); | 614 | EXPORT_SYMBOL(copy_from_iter_nocache); |
590 | 615 | ||
616 | bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) | ||
617 | { | ||
618 | char *to = addr; | ||
619 | if (unlikely(i->type & ITER_PIPE)) { | ||
620 | WARN_ON(1); | ||
621 | return false; | ||
622 | } | ||
623 | if (unlikely(i->count < bytes)) \ | ||
624 | return false; | ||
625 | iterate_all_kinds(i, bytes, v, ({ | ||
626 | if (__copy_from_user_nocache((to += v.iov_len) - v.iov_len, | ||
627 | v.iov_base, v.iov_len)) | ||
628 | return false; | ||
629 | 0;}), | ||
630 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, | ||
631 | v.bv_offset, v.bv_len), | ||
632 | memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) | ||
633 | ) | ||
634 | |||
635 | iov_iter_advance(i, bytes); | ||
636 | return true; | ||
637 | } | ||
638 | EXPORT_SYMBOL(copy_from_iter_full_nocache); | ||
639 | |||
591 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, | 640 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, |
592 | struct iov_iter *i) | 641 | struct iov_iter *i) |
593 | { | 642 | { |
@@ -1009,7 +1058,7 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | |||
1009 | } | 1058 | } |
1010 | iterate_and_advance(i, bytes, v, ({ | 1059 | iterate_and_advance(i, bytes, v, ({ |
1011 | int err = 0; | 1060 | int err = 0; |
1012 | next = csum_and_copy_from_user(v.iov_base, | 1061 | next = csum_and_copy_from_user(v.iov_base, |
1013 | (to += v.iov_len) - v.iov_len, | 1062 | (to += v.iov_len) - v.iov_len, |
1014 | v.iov_len, 0, &err); | 1063 | v.iov_len, 0, &err); |
1015 | if (!err) { | 1064 | if (!err) { |
@@ -1038,6 +1087,51 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | |||
1038 | } | 1087 | } |
1039 | EXPORT_SYMBOL(csum_and_copy_from_iter); | 1088 | EXPORT_SYMBOL(csum_and_copy_from_iter); |
1040 | 1089 | ||
1090 | bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, | ||
1091 | struct iov_iter *i) | ||
1092 | { | ||
1093 | char *to = addr; | ||
1094 | __wsum sum, next; | ||
1095 | size_t off = 0; | ||
1096 | sum = *csum; | ||
1097 | if (unlikely(i->type & ITER_PIPE)) { | ||
1098 | WARN_ON(1); | ||
1099 | return false; | ||
1100 | } | ||
1101 | if (unlikely(i->count < bytes)) | ||
1102 | return false; | ||
1103 | iterate_all_kinds(i, bytes, v, ({ | ||
1104 | int err = 0; | ||
1105 | next = csum_and_copy_from_user(v.iov_base, | ||
1106 | (to += v.iov_len) - v.iov_len, | ||
1107 | v.iov_len, 0, &err); | ||
1108 | if (err) | ||
1109 | return false; | ||
1110 | sum = csum_block_add(sum, next, off); | ||
1111 | off += v.iov_len; | ||
1112 | 0; | ||
1113 | }), ({ | ||
1114 | char *p = kmap_atomic(v.bv_page); | ||
1115 | next = csum_partial_copy_nocheck(p + v.bv_offset, | ||
1116 | (to += v.bv_len) - v.bv_len, | ||
1117 | v.bv_len, 0); | ||
1118 | kunmap_atomic(p); | ||
1119 | sum = csum_block_add(sum, next, off); | ||
1120 | off += v.bv_len; | ||
1121 | }),({ | ||
1122 | next = csum_partial_copy_nocheck(v.iov_base, | ||
1123 | (to += v.iov_len) - v.iov_len, | ||
1124 | v.iov_len, 0); | ||
1125 | sum = csum_block_add(sum, next, off); | ||
1126 | off += v.iov_len; | ||
1127 | }) | ||
1128 | ) | ||
1129 | *csum = sum; | ||
1130 | iov_iter_advance(i, bytes); | ||
1131 | return true; | ||
1132 | } | ||
1133 | EXPORT_SYMBOL(csum_and_copy_from_iter_full); | ||
1134 | |||
1041 | size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | 1135 | size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, |
1042 | struct iov_iter *i) | 1136 | struct iov_iter *i) |
1043 | { | 1137 | { |
@@ -1052,7 +1146,7 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | |||
1052 | iterate_and_advance(i, bytes, v, ({ | 1146 | iterate_and_advance(i, bytes, v, ({ |
1053 | int err = 0; | 1147 | int err = 0; |
1054 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, | 1148 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, |
1055 | v.iov_base, | 1149 | v.iov_base, |
1056 | v.iov_len, 0, &err); | 1150 | v.iov_len, 0, &err); |
1057 | if (!err) { | 1151 | if (!err) { |
1058 | sum = csum_block_add(sum, next, off); | 1152 | sum = csum_block_add(sum, next, off); |