diff options
author | Ming Lei <ming.lei@redhat.com> | 2023-05-19 14:50:28 +0800 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2023-05-19 19:59:17 -0600 |
commit | 38f2dd34410f9070b60969a07ff7d8743b4fd56c (patch) | |
tree | d4bd12a596c36c43114457e5434578e85f31b182 | |
parent | 8284066946e6d9cc979566ce698fe24e7ca0b31e (diff) | |
download | linux-stable-38f2dd34410f9070b60969a07ff7d8743b4fd56c.tar.gz linux-stable-38f2dd34410f9070b60969a07ff7d8743b4fd56c.tar.bz2 linux-stable-38f2dd34410f9070b60969a07ff7d8743b4fd56c.zip |
ublk: support to copy any part of request pages
Add 'offset' to 'struct ublk_map_data', so that ublk_copy_user_pages()
can be used to copy any sub-buffer(linear mapped) of the request.
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20230519065030.351216-6-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/block/ublk_drv.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 353ccdb60729..13523c37a165 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -505,19 +505,36 @@ static void ublk_copy_io_pages(struct ublk_io_iter *data, } } +static bool ublk_advance_io_iter(const struct request *req, + struct ublk_io_iter *iter, unsigned int offset) +{ + struct bio *bio = req->bio; + + for_each_bio(bio) { + if (bio->bi_iter.bi_size > offset) { + iter->bio = bio; + iter->iter = bio->bi_iter; + bio_advance_iter(iter->bio, &iter->iter, offset); + return true; + } + offset -= bio->bi_iter.bi_size; + } + return false; +} + /* * Copy data between request pages and io_iter, and 'offset' * is the start point of linear offset of request. */ static size_t ublk_copy_user_pages(const struct request *req, - struct iov_iter *uiter, int dir) + unsigned offset, struct iov_iter *uiter, int dir) { - struct ublk_io_iter iter = { - .bio = req->bio, - .iter = req->bio->bi_iter, - }; + struct ublk_io_iter iter; size_t done = 0; + if (!ublk_advance_io_iter(req, &iter, offset)) + return 0; + while (iov_iter_count(uiter) && iter.bio) { unsigned nr_pages; size_t len, off; @@ -570,7 +587,7 @@ static int ublk_map_io(const struct ublk_queue *ubq, const struct request *req, import_single_range(dir, u64_to_user_ptr(io->addr), rq_bytes, &iov, &iter); - return ublk_copy_user_pages(req, &iter, dir); + return ublk_copy_user_pages(req, 0, &iter, dir); } return rq_bytes; } @@ -590,7 +607,7 @@ static int ublk_unmap_io(const struct ublk_queue *ubq, import_single_range(dir, u64_to_user_ptr(io->addr), io->res, &iov, &iter); - return ublk_copy_user_pages(req, &iter, dir); + return ublk_copy_user_pages(req, 0, &iter, dir); } return rq_bytes; } |