mirror of
https://github.com/torvalds/linux.git
synced 2024-12-19 09:32:32 +00:00
9210c075ce
There may be a race between nvme_reap_pending_cqes() and nvme_poll(), e.g.,
when doing live reset while polling the nvme device.
CPU X CPU Y
nvme_poll()
nvme_dev_disable()
-> nvme_stop_queues()
-> nvme_suspend_io_queues()
-> nvme_suspend_queue()
-> spin_lock(&nvmeq->cq_poll_lock);
-> nvme_reap_pending_cqes()
-> nvme_process_cq() -> nvme_process_cq()
In the above scenario, the nvme_process_cq() for the same queue may be
running on both CPU X and CPU Y concurrently.
It is much more easier to reproduce the issue when CONFIG_PREEMPT is
enabled in kernel. When CONFIG_PREEMPT is disabled, it would take longer
time for nvme_stop_queues()-->blk_mq_quiesce_queue() to wait for grace
period.
This patch protects nvme_process_cq() with nvmeq->cq_poll_lock in
nvme_reap_pending_cqes().
Fixes:
|
||
---|---|---|
.. | ||
core.c | ||
fabrics.c | ||
fabrics.h | ||
fault_inject.c | ||
fc.c | ||
hwmon.c | ||
Kconfig | ||
lightnvm.c | ||
Makefile | ||
multipath.c | ||
nvme.h | ||
pci.c | ||
rdma.c | ||
tcp.c | ||
trace.c | ||
trace.h |