From: Kanchan Joshi <joshi.k@xxxxxxxxxxx> if io_uring sends passthrough command with IORING_URING_CMD_FIXED flag, use the pre-registered buffer for IO (non-vectored variant). Pass the buffer/length to io_uring and get the bvec iterator for the range. Next, pass this bvec to block-layer and obtain a bio/request for subsequent processing. Signed-off-by: Kanchan Joshi <joshi.k@xxxxxxxxxxx> Suggested-by: Christoph Hellwig <hch@xxxxxx> --- drivers/nvme/host/ioctl.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index 4a7e45a263b6..25a68e8c60db 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -95,21 +95,31 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, void *meta = NULL; int ret; - if (!vec) - ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen, - GFP_KERNEL); - else { + if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) { + struct iov_iter iter; + + /* fixedbufs is only for non-vectored io */ + if (WARN_ON_ONCE(vec)) + return -EINVAL; + ret = io_uring_cmd_import_fixed(ubuffer, bufflen, + rq_data_dir(req), &iter, ioucmd); + if (ret < 0) + goto out; + ret = blk_rq_map_user_iov(q, req, NULL, &iter, GFP_KERNEL); + } else if (vec) { struct iovec fast_iov[UIO_FASTIOV]; struct iovec *iov = fast_iov; struct iov_iter iter; - ret = import_iovec(rq_data_dir(req), ubuffer, bufflen, - UIO_FASTIOV, &iov, &iter); + ret = import_iovec(rq_data_dir(req), nvme_to_user_ptr(ubuffer), + bufflen, UIO_FASTIOV, &iov, &iter); if (ret < 0) goto out; - ret = blk_rq_map_user_iov(q, req, NULL, &iter, GFP_KERNEL); kfree(iov); + } else { + ret = blk_rq_map_user(q, req, NULL, + nvme_to_user_ptr(ubuffer), bufflen, GFP_KERNEL); } if (ret) goto out; -- 2.25.1