Skip to content

Commit ae5e688

Browse files
keithbuschaxboe
authored andcommitted
nvme: use return value from blk_execute_rq()
We don't have an nvme status to report if the driver's .queue_rq() returns an error without dispatching the requested nvme command. Check the return value from blk_execute_rq() for all passthrough commands so the caller may know their command was not successful. If the command is from the target passthrough interface and fails to dispatch, synthesize the response back to the host as a internal target error. Signed-off-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Link: https://lore.kernel.org/r/20210610214437.641245-5-kbusch@kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent fb9b16e commit ae5e688

4 files changed

Lines changed: 33 additions & 18 deletions

File tree

drivers/nvme/host/core.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ EXPORT_SYMBOL_NS_GPL(nvme_put_ns, NVME_TARGET_PASSTHRU);
609609

610610
static inline void nvme_clear_nvme_request(struct request *req)
611611
{
612+
nvme_req(req)->status = 0;
612613
nvme_req(req)->retries = 0;
613614
nvme_req(req)->flags = 0;
614615
req->rq_flags |= RQF_DONTPREP;
@@ -1031,6 +1032,25 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req)
10311032
}
10321033
EXPORT_SYMBOL_GPL(nvme_setup_cmd);
10331034

1035+
/*
1036+
* Return values:
1037+
* 0: success
1038+
* >0: nvme controller's cqe status response
1039+
* <0: kernel error in lieu of controller response
1040+
*/
1041+
static int nvme_execute_rq(struct gendisk *disk, struct request *rq,
1042+
bool at_head)
1043+
{
1044+
blk_status_t status;
1045+
1046+
status = blk_execute_rq(disk, rq, at_head);
1047+
if (nvme_req(rq)->flags & NVME_REQ_CANCELLED)
1048+
return -EINTR;
1049+
if (nvme_req(rq)->status)
1050+
return nvme_req(rq)->status;
1051+
return blk_status_to_errno(status);
1052+
}
1053+
10341054
/*
10351055
* Returns 0 on success. If the result is negative, it's a Linux error code;
10361056
* if the result is positive, it's an NVM Express status code
@@ -1059,13 +1079,9 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
10591079
goto out;
10601080
}
10611081

1062-
blk_execute_rq(NULL, req, at_head);
1063-
if (result)
1082+
ret = nvme_execute_rq(NULL, req, at_head);
1083+
if (result && ret >= 0)
10641084
*result = nvme_req(req)->result;
1065-
if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
1066-
ret = -EINTR;
1067-
else
1068-
ret = nvme_req(req)->status;
10691085
out:
10701086
blk_mq_free_request(req);
10711087
return ret;
@@ -1153,18 +1169,21 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
11531169
}
11541170
}
11551171

1156-
void nvme_execute_passthru_rq(struct request *rq)
1172+
int nvme_execute_passthru_rq(struct request *rq)
11571173
{
11581174
struct nvme_command *cmd = nvme_req(rq)->cmd;
11591175
struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl;
11601176
struct nvme_ns *ns = rq->q->queuedata;
11611177
struct gendisk *disk = ns ? ns->disk : NULL;
11621178
u32 effects;
1179+
int ret;
11631180

11641181
effects = nvme_passthru_start(ctrl, ns, cmd->common.opcode);
1165-
blk_execute_rq(disk, rq, 0);
1182+
ret = nvme_execute_rq(disk, rq, false);
11661183
if (effects) /* nothing to be done for zero cmd effects */
11671184
nvme_passthru_end(ctrl, effects);
1185+
1186+
return ret;
11681187
}
11691188
EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
11701189

drivers/nvme/host/ioctl.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
9393
}
9494
}
9595

96-
nvme_execute_passthru_rq(req);
97-
if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
98-
ret = -EINTR;
99-
else
100-
ret = nvme_req(req)->status;
96+
ret = nvme_execute_passthru_rq(req);
10197
if (result)
10298
*result = le64_to_cpu(nvme_req(req)->result.u64);
10399
if (meta && !ret && !write) {

drivers/nvme/host/nvme.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
876876

877877
u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
878878
u8 opcode);
879-
void nvme_execute_passthru_rq(struct request *rq);
879+
int nvme_execute_passthru_rq(struct request *rq);
880880
struct nvme_ctrl *nvme_ctrl_from_file(struct file *file);
881881
struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid);
882882
void nvme_put_ns(struct nvme_ns *ns);

drivers/nvme/target/passthru.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,10 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
153153
{
154154
struct nvmet_req *req = container_of(w, struct nvmet_req, p.work);
155155
struct request *rq = req->p.rq;
156-
u16 status;
156+
int status;
157157

158-
nvme_execute_passthru_rq(rq);
158+
status = nvme_execute_passthru_rq(rq);
159159

160-
status = nvme_req(rq)->status;
161160
if (status == NVME_SC_SUCCESS &&
162161
req->cmd->common.opcode == nvme_admin_identify) {
163162
switch (req->cmd->identify.cns) {
@@ -168,7 +167,8 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
168167
nvmet_passthru_override_id_ns(req);
169168
break;
170169
}
171-
}
170+
} else if (status < 0)
171+
status = NVME_SC_INTERNAL;
172172

173173
req->cqe->result = nvme_req(rq)->result;
174174
nvmet_req_complete(req, status);

0 commit comments

Comments
 (0)