Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: use rq_for_each_segment() for user copy

ublk_advance_io_iter() and ublk_copy_io_pages() currently open-code the
iteration over the request's bvecs. Switch to the rq_for_each_segment()
macro provided by blk-mq to avoid reaching into the bio internals and
simplify the code.

Suggested-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Caleb Sander Mateos and committed by
Jens Axboe
e87d66ab 2299ceec

+19 -51
+19 -51
drivers/block/ublk_drv.c
··· 913 913 .report_zones = ublk_report_zones, 914 914 }; 915 915 916 - struct ublk_io_iter { 917 - struct bio *bio; 918 - struct bvec_iter iter; 919 - }; 920 - 921 - /* return how many bytes are copied */ 922 - static size_t ublk_copy_io_pages(struct ublk_io_iter *data, 923 - struct iov_iter *uiter, int dir) 916 + /* 917 + * Copy data between request pages and io_iter, and 'offset' 918 + * is the start point of linear offset of request. 919 + */ 920 + static size_t ublk_copy_user_pages(const struct request *req, 921 + unsigned offset, struct iov_iter *uiter, int dir) 924 922 { 923 + struct req_iterator iter; 924 + struct bio_vec bv; 925 925 size_t done = 0; 926 926 927 - for (;;) { 928 - struct bio_vec bv = bio_iter_iovec(data->bio, data->iter); 929 - void *bv_buf = bvec_kmap_local(&bv); 927 + rq_for_each_segment(bv, req, iter) { 928 + void *bv_buf; 930 929 size_t copied; 931 930 931 + if (offset >= bv.bv_len) { 932 + offset -= bv.bv_len; 933 + continue; 934 + } 935 + 936 + bv.bv_offset += offset; 937 + bv.bv_len -= offset; 938 + bv_buf = bvec_kmap_local(&bv); 932 939 if (dir == ITER_DEST) 933 940 copied = copy_to_iter(bv_buf, bv.bv_len, uiter); 934 941 else ··· 947 940 if (copied < bv.bv_len) 948 941 break; 949 942 950 - /* advance bio */ 951 - bio_advance_iter_single(data->bio, &data->iter, copied); 952 - if (!data->iter.bi_size) { 953 - data->bio = data->bio->bi_next; 954 - if (data->bio == NULL) 955 - break; 956 - data->iter = data->bio->bi_iter; 957 - } 943 + offset = 0; 958 944 } 959 945 return done; 960 - } 961 - 962 - static bool ublk_advance_io_iter(const struct request *req, 963 - struct ublk_io_iter *iter, unsigned int offset) 964 - { 965 - struct bio *bio = req->bio; 966 - 967 - for_each_bio(bio) { 968 - if (bio->bi_iter.bi_size > offset) { 969 - iter->bio = bio; 970 - iter->iter = bio->bi_iter; 971 - bio_advance_iter(iter->bio, &iter->iter, offset); 972 - return true; 973 - } 974 - offset -= bio->bi_iter.bi_size; 975 - } 976 - return false; 977 - } 978 - 979 - /* 980 - * Copy data between request pages and io_iter, and 'offset' 981 - * is the start point of linear offset of request. 982 - */ 983 - static size_t ublk_copy_user_pages(const struct request *req, 984 - unsigned offset, struct iov_iter *uiter, int dir) 985 - { 986 - struct ublk_io_iter iter; 987 - 988 - if (!ublk_advance_io_iter(req, &iter, offset)) 989 - return 0; 990 - 991 - return ublk_copy_io_pages(&iter, uiter, dir); 992 946 } 993 947 994 948 static inline bool ublk_need_map_req(const struct request *req)