diff options
author | Sagi Grimberg <sagi@grimberg.me> | 2017-03-06 19:46:20 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-12-20 12:07:25 +0300 |
commit | 571e47760de55281834f28a54f75d51285e7787d (patch) | |
tree | 2a10fc5c50a62cf2597f86b9f7c193bb50871942 /drivers/nvme/target | |
parent | af0cee086b0920612de5d6ad2a8f406792b5aa9d (diff) | |
download | linux-571e47760de55281834f28a54f75d51285e7787d.tar.xz |
nvmet: confirm sq percpu has scheduled and switched to atomic
[ Upstream commit d11ea004a458b982e19b188c386e25a9b66ec446 ]
percpu_ref_kill is not enough to prevent subsequent
percpu_ref_tryget_live from failing. Hence call
perfcpu_ref_kill_confirm to make it safe.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/nvme/target')
-rw-r--r-- | drivers/nvme/target/core.c | 11 | ||||
-rw-r--r-- | drivers/nvme/target/nvmet.h | 1 |
2 files changed, 11 insertions, 1 deletions
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index fbd6d487103f..c89d68a76f3d 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -422,6 +422,13 @@ void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, ctrl->sqs[qid] = sq; } +static void nvmet_confirm_sq(struct percpu_ref *ref) +{ + struct nvmet_sq *sq = container_of(ref, struct nvmet_sq, ref); + + complete(&sq->confirm_done); +} + void nvmet_sq_destroy(struct nvmet_sq *sq) { /* @@ -430,7 +437,8 @@ void nvmet_sq_destroy(struct nvmet_sq *sq) */ if (sq->ctrl && sq->ctrl->sqs && sq->ctrl->sqs[0] == sq) nvmet_async_events_free(sq->ctrl); - percpu_ref_kill(&sq->ref); + percpu_ref_kill_and_confirm(&sq->ref, nvmet_confirm_sq); + wait_for_completion(&sq->confirm_done); wait_for_completion(&sq->free_done); percpu_ref_exit(&sq->ref); @@ -458,6 +466,7 @@ int nvmet_sq_init(struct nvmet_sq *sq) return ret; } init_completion(&sq->free_done); + init_completion(&sq->confirm_done); return 0; } diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 7655a351320f..26b87dc843d2 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -73,6 +73,7 @@ struct nvmet_sq { u16 qid; u16 size; struct completion free_done; + struct completion confirm_done; }; /** |