Skip to content

Commit e87d66a

Browse files
calebsanderaxboe
authored andcommitted
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 <[email protected]> Signed-off-by: Caleb Sander Mateos <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 2299cee commit e87d66a

1 file changed

Lines changed: 19 additions & 51 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -913,22 +913,29 @@ static const struct block_device_operations ub_fops = {
913913
.report_zones = ublk_report_zones,
914914
};
915915

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)
924922
{
923+
struct req_iterator iter;
924+
struct bio_vec bv;
925925
size_t done = 0;
926926

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;
930929
size_t copied;
931930

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);
932939
if (dir == ITER_DEST)
933940
copied = copy_to_iter(bv_buf, bv.bv_len, uiter);
934941
else
@@ -940,50 +947,11 @@ static size_t ublk_copy_io_pages(struct ublk_io_iter *data,
940947
if (copied < bv.bv_len)
941948
break;
942949

943-
/* advance bio */
944-
bio_advance_iter_single(data->bio, &data->iter, copied);
945-
if (!data->iter.bi_size) {
946-
data->bio = data->bio->bi_next;
947-
if (data->bio == NULL)
948-
break;
949-
data->iter = data->bio->bi_iter;
950-
}
950+
offset = 0;
951951
}
952952
return done;
953953
}
954954

955-
static bool ublk_advance_io_iter(const struct request *req,
956-
struct ublk_io_iter *iter, unsigned int offset)
957-
{
958-
struct bio *bio = req->bio;
959-
960-
for_each_bio(bio) {
961-
if (bio->bi_iter.bi_size > offset) {
962-
iter->bio = bio;
963-
iter->iter = bio->bi_iter;
964-
bio_advance_iter(iter->bio, &iter->iter, offset);
965-
return true;
966-
}
967-
offset -= bio->bi_iter.bi_size;
968-
}
969-
return false;
970-
}
971-
972-
/*
973-
* Copy data between request pages and io_iter, and 'offset'
974-
* is the start point of linear offset of request.
975-
*/
976-
static size_t ublk_copy_user_pages(const struct request *req,
977-
unsigned offset, struct iov_iter *uiter, int dir)
978-
{
979-
struct ublk_io_iter iter;
980-
981-
if (!ublk_advance_io_iter(req, &iter, offset))
982-
return 0;
983-
984-
return ublk_copy_io_pages(&iter, uiter, dir);
985-
}
986-
987955
static inline bool ublk_need_map_req(const struct request *req)
988956
{
989957
return ublk_rq_has_data(req) && req_op(req) == REQ_OP_WRITE;

0 commit comments

Comments
 (0)