Skip to content

Commit a347c15

Browse files
committed
Merge tag 'nvme-5.14-2021-07-15' of git://git.infradead.org/nvme into block-5.14
Pull NVMe fixes from Christoph: "nvme fixes for Linux 5.14 - fix various races in nvme-pci when shutting down just after probing (Casey Chen) - fix a net_device leak in nvme-tcp (Prabhakar Kushwaha)" * tag 'nvme-5.14-2021-07-15' of git://git.infradead.org/nvme: nvme-pci: do not call nvme_dev_remove_admin from nvme_remove nvme-pci: fix multiple races in nvme_setup_io_queues nvme-tcp: use __dev_get_by_name instead dev_get_by_name for OPT_HOST_IFACE
2 parents 16ad3db + 251ef6f commit a347c15

File tree

2 files changed

+59
-12
lines changed

2 files changed

+59
-12
lines changed

drivers/nvme/host/pci.c

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,6 +1554,28 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
15541554
wmb(); /* ensure the first interrupt sees the initialization */
15551555
}
15561556

1557+
/*
1558+
* Try getting shutdown_lock while setting up IO queues.
1559+
*/
1560+
static int nvme_setup_io_queues_trylock(struct nvme_dev *dev)
1561+
{
1562+
/*
1563+
* Give up if the lock is being held by nvme_dev_disable.
1564+
*/
1565+
if (!mutex_trylock(&dev->shutdown_lock))
1566+
return -ENODEV;
1567+
1568+
/*
1569+
* Controller is in wrong state, fail early.
1570+
*/
1571+
if (dev->ctrl.state != NVME_CTRL_CONNECTING) {
1572+
mutex_unlock(&dev->shutdown_lock);
1573+
return -ENODEV;
1574+
}
1575+
1576+
return 0;
1577+
}
1578+
15571579
static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled)
15581580
{
15591581
struct nvme_dev *dev = nvmeq->dev;
@@ -1582,19 +1604,24 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled)
15821604
goto release_cq;
15831605

15841606
nvmeq->cq_vector = vector;
1585-
nvme_init_queue(nvmeq, qid);
15861607

1608+
result = nvme_setup_io_queues_trylock(dev);
1609+
if (result)
1610+
return result;
1611+
nvme_init_queue(nvmeq, qid);
15871612
if (!polled) {
15881613
result = queue_request_irq(nvmeq);
15891614
if (result < 0)
15901615
goto release_sq;
15911616
}
15921617

15931618
set_bit(NVMEQ_ENABLED, &nvmeq->flags);
1619+
mutex_unlock(&dev->shutdown_lock);
15941620
return result;
15951621

15961622
release_sq:
15971623
dev->online_queues--;
1624+
mutex_unlock(&dev->shutdown_lock);
15981625
adapter_delete_sq(dev, qid);
15991626
release_cq:
16001627
adapter_delete_cq(dev, qid);
@@ -2167,7 +2194,18 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
21672194
if (nr_io_queues == 0)
21682195
return 0;
21692196

2170-
clear_bit(NVMEQ_ENABLED, &adminq->flags);
2197+
/*
2198+
* Free IRQ resources as soon as NVMEQ_ENABLED bit transitions
2199+
* from set to unset. If there is a window to it is truely freed,
2200+
* pci_free_irq_vectors() jumping into this window will crash.
2201+
* And take lock to avoid racing with pci_free_irq_vectors() in
2202+
* nvme_dev_disable() path.
2203+
*/
2204+
result = nvme_setup_io_queues_trylock(dev);
2205+
if (result)
2206+
return result;
2207+
if (test_and_clear_bit(NVMEQ_ENABLED, &adminq->flags))
2208+
pci_free_irq(pdev, 0, adminq);
21712209

21722210
if (dev->cmb_use_sqes) {
21732211
result = nvme_cmb_qdepth(dev, nr_io_queues,
@@ -2183,14 +2221,17 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
21832221
result = nvme_remap_bar(dev, size);
21842222
if (!result)
21852223
break;
2186-
if (!--nr_io_queues)
2187-
return -ENOMEM;
2224+
if (!--nr_io_queues) {
2225+
result = -ENOMEM;
2226+
goto out_unlock;
2227+
}
21882228
} while (1);
21892229
adminq->q_db = dev->dbs;
21902230

21912231
retry:
21922232
/* Deregister the admin queue's interrupt */
2193-
pci_free_irq(pdev, 0, adminq);
2233+
if (test_and_clear_bit(NVMEQ_ENABLED, &adminq->flags))
2234+
pci_free_irq(pdev, 0, adminq);
21942235

21952236
/*
21962237
* If we enable msix early due to not intx, disable it again before
@@ -2199,8 +2240,10 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
21992240
pci_free_irq_vectors(pdev);
22002241

22012242
result = nvme_setup_irqs(dev, nr_io_queues);
2202-
if (result <= 0)
2203-
return -EIO;
2243+
if (result <= 0) {
2244+
result = -EIO;
2245+
goto out_unlock;
2246+
}
22042247

22052248
dev->num_vecs = result;
22062249
result = max(result - 1, 1);
@@ -2214,8 +2257,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
22142257
*/
22152258
result = queue_request_irq(adminq);
22162259
if (result)
2217-
return result;
2260+
goto out_unlock;
22182261
set_bit(NVMEQ_ENABLED, &adminq->flags);
2262+
mutex_unlock(&dev->shutdown_lock);
22192263

22202264
result = nvme_create_io_queues(dev);
22212265
if (result || dev->online_queues < 2)
@@ -2224,6 +2268,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
22242268
if (dev->online_queues - 1 < dev->max_qid) {
22252269
nr_io_queues = dev->online_queues - 1;
22262270
nvme_disable_io_queues(dev);
2271+
result = nvme_setup_io_queues_trylock(dev);
2272+
if (result)
2273+
return result;
22272274
nvme_suspend_io_queues(dev);
22282275
goto retry;
22292276
}
@@ -2232,6 +2279,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
22322279
dev->io_queues[HCTX_TYPE_READ],
22332280
dev->io_queues[HCTX_TYPE_POLL]);
22342281
return 0;
2282+
out_unlock:
2283+
mutex_unlock(&dev->shutdown_lock);
2284+
return result;
22352285
}
22362286

22372287
static void nvme_del_queue_end(struct request *req, blk_status_t error)
@@ -2962,7 +3012,6 @@ static void nvme_remove(struct pci_dev *pdev)
29623012
if (!pci_device_is_present(pdev)) {
29633013
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DEAD);
29643014
nvme_dev_disable(dev, true);
2965-
nvme_dev_remove_admin(dev);
29663015
}
29673016

29683017
flush_work(&dev->ctrl.reset_work);

drivers/nvme/host/tcp.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ struct nvme_tcp_ctrl {
123123
struct blk_mq_tag_set admin_tag_set;
124124
struct sockaddr_storage addr;
125125
struct sockaddr_storage src_addr;
126-
struct net_device *ndev;
127126
struct nvme_ctrl ctrl;
128127

129128
struct work_struct err_work;
@@ -2533,8 +2532,7 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
25332532
}
25342533

25352534
if (opts->mask & NVMF_OPT_HOST_IFACE) {
2536-
ctrl->ndev = dev_get_by_name(&init_net, opts->host_iface);
2537-
if (!ctrl->ndev) {
2535+
if (!__dev_get_by_name(&init_net, opts->host_iface)) {
25382536
pr_err("invalid interface passed: %s\n",
25392537
opts->host_iface);
25402538
ret = -ENODEV;

0 commit comments

Comments
 (0)