aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-03-20 20:10:21 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:26:45 -0400
commitac15ac0669d5f5ce7fddec0d9cf3721c42d77a2c (patch)
tree4597aa9d1c2283823512a1af468b547994d2b858
parentc0fec3a98bd6c4d992f191ee1aa0b3599213f3d4 (diff)
lift iov_iter into {compat_,}do_readv_writev()
get it closer to matching {compat_,}rw_copy_check_uvector(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/read_write.c54
1 files changed, 23 insertions, 31 deletions
diff --git a/fs/read_write.c b/fs/read_write.c
index 99a6ef946d01..11980f164432 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -695,25 +695,23 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
695} 695}
696EXPORT_SYMBOL(iov_shorten); 696EXPORT_SYMBOL(iov_shorten);
697 697
698static ssize_t do_iter_readv_writev(struct file *filp, int rw, const struct iovec *iov, 698static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
699 unsigned long nr_segs, size_t len, loff_t *ppos, iter_fn_t fn) 699 loff_t *ppos, iter_fn_t fn)
700{ 700{
701 struct kiocb kiocb; 701 struct kiocb kiocb;
702 struct iov_iter iter;
703 ssize_t ret; 702 ssize_t ret;
704 703
705 init_sync_kiocb(&kiocb, filp); 704 init_sync_kiocb(&kiocb, filp);
706 kiocb.ki_pos = *ppos; 705 kiocb.ki_pos = *ppos;
707 706
708 iov_iter_init(&iter, rw, iov, nr_segs, len); 707 ret = fn(&kiocb, iter);
709 ret = fn(&kiocb, &iter);
710 BUG_ON(ret == -EIOCBQUEUED); 708 BUG_ON(ret == -EIOCBQUEUED);
711 *ppos = kiocb.ki_pos; 709 *ppos = kiocb.ki_pos;
712 return ret; 710 return ret;
713} 711}
714 712
715static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, 713static ssize_t do_sync_readv_writev(struct file *filp, struct iov_iter *iter,
716 unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) 714 loff_t *ppos, iov_fn_t fn)
717{ 715{
718 struct kiocb kiocb; 716 struct kiocb kiocb;
719 ssize_t ret; 717 ssize_t ret;
@@ -721,30 +719,23 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
721 init_sync_kiocb(&kiocb, filp); 719 init_sync_kiocb(&kiocb, filp);
722 kiocb.ki_pos = *ppos; 720 kiocb.ki_pos = *ppos;
723 721
724 ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos); 722 ret = fn(&kiocb, iter->iov, iter->nr_segs, kiocb.ki_pos);
725 BUG_ON(ret == -EIOCBQUEUED); 723 BUG_ON(ret == -EIOCBQUEUED);
726 *ppos = kiocb.ki_pos; 724 *ppos = kiocb.ki_pos;
727 return ret; 725 return ret;
728} 726}
729 727
730/* Do it by hand, with file-ops */ 728/* Do it by hand, with file-ops */
731static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, 729static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
732 unsigned long nr_segs, loff_t *ppos, io_fn_t fn) 730 loff_t *ppos, io_fn_t fn)
733{ 731{
734 struct iovec *vector = iov;
735 ssize_t ret = 0; 732 ssize_t ret = 0;
736 733
737 while (nr_segs > 0) { 734 while (iov_iter_count(iter)) {
738 void __user *base; 735 struct iovec iovec = iov_iter_iovec(iter);
739 size_t len;
740 ssize_t nr; 736 ssize_t nr;
741 737
742 base = vector->iov_base; 738 nr = fn(filp, iovec.iov_base, iovec.iov_len, ppos);
743 len = vector->iov_len;
744 vector++;
745 nr_segs--;
746
747 nr = fn(filp, base, len, ppos);
748 739
749 if (nr < 0) { 740 if (nr < 0) {
750 if (!ret) 741 if (!ret)
@@ -752,8 +743,9 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
752 break; 743 break;
753 } 744 }
754 ret += nr; 745 ret += nr;
755 if (nr != len) 746 if (nr != iovec.iov_len)
756 break; 747 break;
748 iov_iter_advance(iter, nr);
757 } 749 }
758 750
759 return ret; 751 return ret;
@@ -844,6 +836,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
844 size_t tot_len; 836 size_t tot_len;
845 struct iovec iovstack[UIO_FASTIOV]; 837 struct iovec iovstack[UIO_FASTIOV];
846 struct iovec *iov = iovstack; 838 struct iovec *iov = iovstack;
839 struct iov_iter iter;
847 ssize_t ret; 840 ssize_t ret;
848 io_fn_t fn; 841 io_fn_t fn;
849 iov_fn_t fnv; 842 iov_fn_t fnv;
@@ -853,6 +846,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
853 ARRAY_SIZE(iovstack), iovstack, &iov); 846 ARRAY_SIZE(iovstack), iovstack, &iov);
854 if (ret <= 0) 847 if (ret <= 0)
855 goto out; 848 goto out;
849 iov_iter_init(&iter, type, iov, nr_segs, ret);
856 850
857 tot_len = ret; 851 tot_len = ret;
858 ret = rw_verify_area(type, file, pos, tot_len); 852 ret = rw_verify_area(type, file, pos, tot_len);
@@ -872,13 +866,11 @@ static ssize_t do_readv_writev(int type, struct file *file,
872 } 866 }
873 867
874 if (iter_fn) 868 if (iter_fn)
875 ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len, 869 ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
876 pos, iter_fn);
877 else if (fnv) 870 else if (fnv)
878 ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, 871 ret = do_sync_readv_writev(file, &iter, pos, fnv);
879 pos, fnv);
880 else 872 else
881 ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); 873 ret = do_loop_readv_writev(file, &iter, pos, fn);
882 874
883 if (type != READ) 875 if (type != READ)
884 file_end_write(file); 876 file_end_write(file);
@@ -1024,6 +1016,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
1024 compat_ssize_t tot_len; 1016 compat_ssize_t tot_len;
1025 struct iovec iovstack[UIO_FASTIOV]; 1017 struct iovec iovstack[UIO_FASTIOV];
1026 struct iovec *iov = iovstack; 1018 struct iovec *iov = iovstack;
1019 struct iov_iter iter;
1027 ssize_t ret; 1020 ssize_t ret;
1028 io_fn_t fn; 1021 io_fn_t fn;
1029 iov_fn_t fnv; 1022 iov_fn_t fnv;
@@ -1033,6 +1026,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
1033 UIO_FASTIOV, iovstack, &iov); 1026 UIO_FASTIOV, iovstack, &iov);
1034 if (ret <= 0) 1027 if (ret <= 0)
1035 goto out; 1028 goto out;
1029 iov_iter_init(&iter, type, iov, nr_segs, ret);
1036 1030
1037 tot_len = ret; 1031 tot_len = ret;
1038 ret = rw_verify_area(type, file, pos, tot_len); 1032 ret = rw_verify_area(type, file, pos, tot_len);
@@ -1052,13 +1046,11 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
1052 } 1046 }
1053 1047
1054 if (iter_fn) 1048 if (iter_fn)
1055 ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len, 1049 ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
1056 pos, iter_fn);
1057 else if (fnv) 1050 else if (fnv)
1058 ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, 1051 ret = do_sync_readv_writev(file, &iter, pos, fnv);
1059 pos, fnv);
1060 else 1052 else
1061 ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); 1053 ret = do_loop_readv_writev(file, &iter, pos, fn);
1062 1054
1063 if (type != READ) 1055 if (type != READ)
1064 file_end_write(file); 1056 file_end_write(file);