Skip to content

Commit db339b4

Browse files
calebsanderaxboe
authored andcommitted
ublk: don't mutate struct bio_vec in iteration
__bio_for_each_segment() uses the returned struct bio_vec's bv_len field to advance the struct bvec_iter at the end of each loop iteration. So it's incorrect to modify it during the loop. Don't assign to bv_len (or bv_offset, for that matter) in ublk_copy_user_pages(). Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> Fixes: e87d66a ("ublk: use rq_for_each_segment() for user copy") Reviewed-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent cfdeb58 commit db339b4

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,7 @@ static size_t ublk_copy_user_pages(const struct request *req,
926926
size_t done = 0;
927927

928928
rq_for_each_segment(bv, req, iter) {
929+
unsigned len;
929930
void *bv_buf;
930931
size_t copied;
931932

@@ -934,18 +935,17 @@ static size_t ublk_copy_user_pages(const struct request *req,
934935
continue;
935936
}
936937

937-
bv.bv_offset += offset;
938-
bv.bv_len -= offset;
939-
bv_buf = bvec_kmap_local(&bv);
938+
len = bv.bv_len - offset;
939+
bv_buf = kmap_local_page(bv.bv_page) + bv.bv_offset + offset;
940940
if (dir == ITER_DEST)
941-
copied = copy_to_iter(bv_buf, bv.bv_len, uiter);
941+
copied = copy_to_iter(bv_buf, len, uiter);
942942
else
943-
copied = copy_from_iter(bv_buf, bv.bv_len, uiter);
943+
copied = copy_from_iter(bv_buf, len, uiter);
944944

945945
kunmap_local(bv_buf);
946946

947947
done += copied;
948-
if (copied < bv.bv_len)
948+
if (copied < len)
949949
break;
950950

951951
offset = 0;

0 commit comments

Comments
 (0)