diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-03-20 20:10:21 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:26:45 -0400 |
commit | ac15ac0669d5f5ce7fddec0d9cf3721c42d77a2c (patch) | |
tree | 4597aa9d1c2283823512a1af468b547994d2b858 | |
parent | c0fec3a98bd6c4d992f191ee1aa0b3599213f3d4 (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.c | 54 |
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 | } |
696 | EXPORT_SYMBOL(iov_shorten); | 696 | EXPORT_SYMBOL(iov_shorten); |
697 | 697 | ||
698 | static ssize_t do_iter_readv_writev(struct file *filp, int rw, const struct iovec *iov, | 698 | static 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 | ||
715 | static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, | 713 | static 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 */ |
731 | static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, | 729 | static 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); |