aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorDongsu Park <dongsu.park@profitbricks.com>2015-01-18 10:16:34 -0500
committerJens Axboe <axboe@fb.com>2015-02-05 11:30:44 -0500
commit9124d3fe21b0947b03f4b87bcfb7acd675d6e85b (patch)
treea3d9e26708dab191bdce78a7a794f45971698694 /block
parent37f19e57a0de3c4a3417aa13ff4d04f1e0dee4b3 (diff)
block: rewrite and split __bio_copy_iov()
Rewrite __bio_copy_iov using the copy_page_{from,to}_iter helpers, and split it into two simpler functions. This commit should contain only literal replacements, without functional changes. Cc: Kent Overstreet <kmo@daterainc.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Dongsu Park <dongsu.park@profitbricks.com> [hch: removed the __bio_copy_iov wrapper] Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Ming Lei <tom.leiming@gmail.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/bio.c90
1 files changed, 56 insertions, 34 deletions
diff --git a/block/bio.c b/block/bio.c
index 0723d4ce8589..f66a4eae16ee 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1036,43 +1036,66 @@ static struct bio_map_data *bio_alloc_map_data(unsigned int iov_count,
1036 sizeof(struct iovec) * iov_count, gfp_mask); 1036 sizeof(struct iovec) * iov_count, gfp_mask);
1037} 1037}
1038 1038
1039static int __bio_copy_iov(struct bio *bio, const struct iov_iter *iter, 1039/**
1040 int to_user, int from_user) 1040 * bio_copy_from_iter - copy all pages from iov_iter to bio
1041 * @bio: The &struct bio which describes the I/O as destination
1042 * @iter: iov_iter as source
1043 *
1044 * Copy all pages from iov_iter to bio.
1045 * Returns 0 on success, or error on failure.
1046 */
1047static int bio_copy_from_iter(struct bio *bio, struct iov_iter iter)
1041{ 1048{
1042 int ret = 0, i; 1049 int i;
1043 struct bio_vec *bvec; 1050 struct bio_vec *bvec;
1044 struct iov_iter iov_iter = *iter;
1045 1051
1046 bio_for_each_segment_all(bvec, bio, i) { 1052 bio_for_each_segment_all(bvec, bio, i) {
1047 char *bv_addr = page_address(bvec->bv_page); 1053 ssize_t ret;
1048 unsigned int bv_len = bvec->bv_len;
1049
1050 while (bv_len && iov_iter.count) {
1051 struct iovec iov = iov_iter_iovec(&iov_iter);
1052 unsigned int bytes = min_t(unsigned int, bv_len,
1053 iov.iov_len);
1054
1055 if (!ret) {
1056 if (to_user)
1057 ret = copy_to_user(iov.iov_base,
1058 bv_addr, bytes);
1059
1060 if (from_user)
1061 ret = copy_from_user(bv_addr,
1062 iov.iov_base,
1063 bytes);
1064
1065 if (ret)
1066 ret = -EFAULT;
1067 }
1068 1054
1069 bv_len -= bytes; 1055 ret = copy_page_from_iter(bvec->bv_page,
1070 bv_addr += bytes; 1056 bvec->bv_offset,
1071 iov_iter_advance(&iov_iter, bytes); 1057 bvec->bv_len,
1072 } 1058 &iter);
1059
1060 if (!iov_iter_count(&iter))
1061 break;
1062
1063 if (ret < bvec->bv_len)
1064 return -EFAULT;
1073 } 1065 }
1074 1066
1075 return ret; 1067 return 0;
1068}
1069
1070/**
1071 * bio_copy_to_iter - copy all pages from bio to iov_iter
1072 * @bio: The &struct bio which describes the I/O as source
1073 * @iter: iov_iter as destination
1074 *
1075 * Copy all pages from bio to iov_iter.
1076 * Returns 0 on success, or error on failure.
1077 */
1078static int bio_copy_to_iter(struct bio *bio, struct iov_iter iter)
1079{
1080 int i;
1081 struct bio_vec *bvec;
1082
1083 bio_for_each_segment_all(bvec, bio, i) {
1084 ssize_t ret;
1085
1086 ret = copy_page_to_iter(bvec->bv_page,
1087 bvec->bv_offset,
1088 bvec->bv_len,
1089 &iter);
1090
1091 if (!iov_iter_count(&iter))
1092 break;
1093
1094 if (ret < bvec->bv_len)
1095 return -EFAULT;
1096 }
1097
1098 return 0;
1076} 1099}
1077 1100
1078static void bio_free_pages(struct bio *bio) 1101static void bio_free_pages(struct bio *bio)
@@ -1101,9 +1124,8 @@ int bio_uncopy_user(struct bio *bio)
1101 * if we're in a workqueue, the request is orphaned, so 1124 * if we're in a workqueue, the request is orphaned, so
1102 * don't copy into a random user address space, just free. 1125 * don't copy into a random user address space, just free.
1103 */ 1126 */
1104 if (current->mm) 1127 if (current->mm && bio_data_dir(bio) == READ)
1105 ret = __bio_copy_iov(bio, &bmd->iter, 1128 ret = bio_copy_to_iter(bio, bmd->iter);
1106 bio_data_dir(bio) == READ, 0);
1107 if (bmd->is_our_pages) 1129 if (bmd->is_our_pages)
1108 bio_free_pages(bio); 1130 bio_free_pages(bio);
1109 } 1131 }
@@ -1228,7 +1250,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
1228 */ 1250 */
1229 if (((iter->type & WRITE) && (!map_data || !map_data->null_mapped)) || 1251 if (((iter->type & WRITE) && (!map_data || !map_data->null_mapped)) ||
1230 (map_data && map_data->from_user)) { 1252 (map_data && map_data->from_user)) {
1231 ret = __bio_copy_iov(bio, iter, 0, 1); 1253 ret = bio_copy_from_iter(bio, *iter);
1232 if (ret) 1254 if (ret)
1233 goto cleanup; 1255 goto cleanup;
1234 } 1256 }