summaryrefslogtreecommitdiffstats
path: root/lib/iov_iter.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-16 13:24:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-16 13:24:44 -0500
commit9a19a6db37ee0b7a6db796b3dcd6bb6e7237d6ea (patch)
tree614d68498eea1c6f9120cae07806f916fd9776bc /lib/iov_iter.c
parentbd9999cd6a5eb899504ce14c1f70c5479143bbbc (diff)
parentc4364f837caf618c2fdb51a2e132cf29dfd1fffa (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro: - more ->d_init() stuff (work.dcache) - pathname resolution cleanups (work.namei) - a few missing iov_iter primitives - copy_from_iter_full() and friends. Either copy the full requested amount, advance the iterator and return true, or fail, return false and do _not_ advance the iterator. Quite a few open-coded callers converted (and became more readable and harder to fuck up that way) (work.iov_iter) - several assorted patches, the big one being logfs removal * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: logfs: remove from tree vfs: fix put_compat_statfs64() does not handle errors namei: fold should_follow_link() with the step into not-followed link namei: pass both WALK_GET and WALK_MORE to should_follow_link() namei: invert WALK_PUT logics namei: shift interpretation of LOOKUP_FOLLOW inside should_follow_link() namei: saner calling conventions for mountpoint_last() namei.c: get rid of user_path_parent() switch getfrag callbacks to ..._full() primitives make skb_add_data,{_nocache}() and skb_copy_to_page_nocache() advance only on success [iov_iter] new primitives - copy_from_iter_full() and friends don't open-code file_inode() ceph: switch to use of ->d_init() ceph: unify dentry_operations instances lustre: switch to use of ->d_init()
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r--lib/iov_iter.c98
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}
570EXPORT_SYMBOL(copy_from_iter); 570EXPORT_SYMBOL(copy_from_iter);
571 571
572bool 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}
595EXPORT_SYMBOL(copy_from_iter_full);
596
572size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 597size_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}
589EXPORT_SYMBOL(copy_from_iter_nocache); 614EXPORT_SYMBOL(copy_from_iter_nocache);
590 615
616bool 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}
638EXPORT_SYMBOL(copy_from_iter_full_nocache);
639
591size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, 640size_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}
1039EXPORT_SYMBOL(csum_and_copy_from_iter); 1088EXPORT_SYMBOL(csum_and_copy_from_iter);
1040 1089
1090bool 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}
1133EXPORT_SYMBOL(csum_and_copy_from_iter_full);
1134
1041size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, 1135size_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);