mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 13:53:33 +00:00
nvme: fix miss command type check
commit31a5978243
upstream. In the function nvme_passthru_end(), only the value of the command opcode is checked, without checking the command type (IO command or Admin command). When we send a Dataset Management command (The opcode of the Dataset Management command is the same as the Set Feature command), kernel thinks it is a set feature command, then sets the controller's keep alive interval, and calls nvme_keep_alive_work(). Signed-off-by: min15.li <min15.li@samsung.com> Reviewed-by: Kanchan Joshi <joshi.k@samsung.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Keith Busch <kbusch@kernel.org> Fixes:b58da2d270
("nvme: update keep alive interval when kato is modified") Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
9c2b4b6577
commit
5e6898b854
4 changed files with 8 additions and 4 deletions
|
@ -1151,7 +1151,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
|
||||||
return effects;
|
return effects;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
|
void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
|
||||||
struct nvme_command *cmd, int status)
|
struct nvme_command *cmd, int status)
|
||||||
{
|
{
|
||||||
if (effects & NVME_CMD_EFFECTS_CSE_MASK) {
|
if (effects & NVME_CMD_EFFECTS_CSE_MASK) {
|
||||||
|
@ -1167,6 +1167,8 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
|
||||||
nvme_queue_scan(ctrl);
|
nvme_queue_scan(ctrl);
|
||||||
flush_work(&ctrl->scan_work);
|
flush_work(&ctrl->scan_work);
|
||||||
}
|
}
|
||||||
|
if (ns)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (cmd->common.opcode) {
|
switch (cmd->common.opcode) {
|
||||||
case nvme_admin_set_features:
|
case nvme_admin_set_features:
|
||||||
|
|
|
@ -147,6 +147,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
|
||||||
unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
|
unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
|
||||||
u32 meta_seed, u64 *result, unsigned timeout, bool vec)
|
u32 meta_seed, u64 *result, unsigned timeout, bool vec)
|
||||||
{
|
{
|
||||||
|
struct nvme_ns *ns = q->queuedata;
|
||||||
struct nvme_ctrl *ctrl;
|
struct nvme_ctrl *ctrl;
|
||||||
struct request *req;
|
struct request *req;
|
||||||
void *meta = NULL;
|
void *meta = NULL;
|
||||||
|
@ -181,7 +182,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
|
||||||
blk_mq_free_request(req);
|
blk_mq_free_request(req);
|
||||||
|
|
||||||
if (effects)
|
if (effects)
|
||||||
nvme_passthru_end(ctrl, effects, cmd, ret);
|
nvme_passthru_end(ctrl, ns, effects, cmd, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1063,7 +1063,7 @@ static inline void nvme_auth_free(struct nvme_ctrl *ctrl) {};
|
||||||
u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
|
u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
|
||||||
u8 opcode);
|
u8 opcode);
|
||||||
int nvme_execute_passthru_rq(struct request *rq, u32 *effects);
|
int nvme_execute_passthru_rq(struct request *rq, u32 *effects);
|
||||||
void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
|
void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
|
||||||
struct nvme_command *cmd, int status);
|
struct nvme_command *cmd, int status);
|
||||||
struct nvme_ctrl *nvme_ctrl_from_file(struct file *file);
|
struct nvme_ctrl *nvme_ctrl_from_file(struct file *file);
|
||||||
struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid);
|
struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid);
|
||||||
|
|
|
@ -216,6 +216,7 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
|
||||||
struct nvmet_req *req = container_of(w, struct nvmet_req, p.work);
|
struct nvmet_req *req = container_of(w, struct nvmet_req, p.work);
|
||||||
struct request *rq = req->p.rq;
|
struct request *rq = req->p.rq;
|
||||||
struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl;
|
struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl;
|
||||||
|
struct nvme_ns *ns = rq->q->queuedata;
|
||||||
u32 effects;
|
u32 effects;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -242,7 +243,7 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
|
||||||
blk_mq_free_request(rq);
|
blk_mq_free_request(rq);
|
||||||
|
|
||||||
if (effects)
|
if (effects)
|
||||||
nvme_passthru_end(ctrl, effects, req->cmd, status);
|
nvme_passthru_end(ctrl, ns, effects, req->cmd, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum rq_end_io_ret nvmet_passthru_req_done(struct request *rq,
|
static enum rq_end_io_ret nvmet_passthru_req_done(struct request *rq,
|
||||||
|
|
Loading…
Reference in a new issue