diff options
author | Jens Axboe <axboe@fb.com> | 2014-12-12 10:53:40 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-12-12 10:53:40 -0500 |
commit | 849c6e7746e4f6317ace6aa7d2fcdcd844e99ddb (patch) | |
tree | a46e807ce51483393beb9e1d8c1ed331e9a023ca /drivers/block | |
parent | fe54303ee2be293c1c5c7a53a152453789cabc2f (diff) |
NVMe: fix race condition in nvme_submit_sync_cmd()
If we have a race between the schedule timing out and the command
completing, we could have the task issuing the command exit
nvme_submit_sync_cmd() while the irq is running sync_completion().
If that happens, we could be corrupting memory, since the stack
that held 'cmdinfo' is no longer valid.
Fix this by always calling nvme_abort_cmd_info(). Once that call
completes, we know that we have either run sync_completion() if
the completion came in, or that we will never run it since we now
have special_completion() as the command callback handler.
Acked-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nvme-core.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index e92bdf4c68fc..b1d5d8797315 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -804,12 +804,19 @@ static int nvme_submit_sync_cmd(struct request *req, struct nvme_command *cmd, | |||
804 | nvme_finish_cmd(nvmeq, req->tag, NULL); | 804 | nvme_finish_cmd(nvmeq, req->tag, NULL); |
805 | set_current_state(TASK_RUNNING); | 805 | set_current_state(TASK_RUNNING); |
806 | } | 806 | } |
807 | schedule_timeout(timeout); | 807 | ret = schedule_timeout(timeout); |
808 | 808 | ||
809 | if (cmdinfo.status == -EINTR) { | 809 | /* |
810 | nvme_abort_cmd_info(nvmeq, blk_mq_rq_to_pdu(req)); | 810 | * Ensure that sync_completion has either run, or that it will |
811 | * never run. | ||
812 | */ | ||
813 | nvme_abort_cmd_info(nvmeq, blk_mq_rq_to_pdu(req)); | ||
814 | |||
815 | /* | ||
816 | * We never got the completion | ||
817 | */ | ||
818 | if (cmdinfo.status == -EINTR) | ||
811 | return -EINTR; | 819 | return -EINTR; |
812 | } | ||
813 | 820 | ||
814 | if (result) | 821 | if (result) |
815 | *result = cmdinfo.result; | 822 | *result = cmdinfo.result; |