aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvme/target/passthru.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvme/target/passthru.c')
-rw-r--r--drivers/nvme/target/passthru.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 8ee94f056898..b9776fc8f08f 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -188,35 +188,31 @@ static void nvmet_passthru_req_done(struct request *rq,
static int nvmet_passthru_map_sg(struct nvmet_req *req, struct request *rq)
{
struct scatterlist *sg;
- int op_flags = 0;
struct bio *bio;
- int i, ret;
+ int i;
if (req->sg_cnt > BIO_MAX_PAGES)
return -EINVAL;
- if (req->cmd->common.opcode == nvme_cmd_flush)
- op_flags = REQ_FUA;
- else if (nvme_is_write(req->cmd))
- op_flags = REQ_SYNC | REQ_IDLE;
-
- bio = bio_alloc(GFP_KERNEL, req->sg_cnt);
- bio->bi_end_io = bio_put;
- bio->bi_opf = req_op(rq) | op_flags;
+ if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) {
+ bio = &req->p.inline_bio;
+ bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec));
+ } else {
+ bio = bio_alloc(GFP_KERNEL, min(req->sg_cnt, BIO_MAX_PAGES));
+ bio->bi_end_io = bio_put;
+ }
+ bio->bi_opf = req_op(rq);
for_each_sg(req->sg, sg, req->sg_cnt, i) {
if (bio_add_pc_page(rq->q, bio, sg_page(sg), sg->length,
sg->offset) < sg->length) {
- bio_put(bio);
+ if (bio != &req->p.inline_bio)
+ bio_put(bio);
return -EINVAL;
}
}
- ret = blk_rq_append_bio(rq, &bio);
- if (unlikely(ret)) {
- bio_put(bio);
- return ret;
- }
+ blk_rq_bio_prep(rq, bio, req->sg_cnt);
return 0;
}
@@ -227,6 +223,7 @@ static void nvmet_passthru_execute_cmd(struct nvmet_req *req)
struct request_queue *q = ctrl->admin_q;
struct nvme_ns *ns = NULL;
struct request *rq = NULL;
+ unsigned int timeout;
u32 effects;
u16 status;
int ret;
@@ -242,14 +239,20 @@ static void nvmet_passthru_execute_cmd(struct nvmet_req *req)
}
q = ns->queue;
+ timeout = req->sq->ctrl->subsys->io_timeout;
+ } else {
+ timeout = req->sq->ctrl->subsys->admin_timeout;
}
- rq = nvme_alloc_request(q, req->cmd, 0, NVME_QID_ANY);
+ rq = nvme_alloc_request(q, req->cmd, 0);
if (IS_ERR(rq)) {
status = NVME_SC_INTERNAL;
goto out_put_ns;
}
+ if (timeout)
+ rq->timeout = timeout;
+
if (req->sg_cnt) {
ret = nvmet_passthru_map_sg(req, rq);
if (unlikely(ret)) {