diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-15 18:44:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-15 18:44:10 -0400 |
commit | 2e572599139d27db3aaf540b0d34f0a4f58dfca1 (patch) | |
tree | a96c8d562d50963c923edd777b60a2dc3749462c | |
parent | f3c9a1abbe9d4c9565fdb0755e2c7814f32d4f62 (diff) | |
parent | a7297a6a3a3322b054592e8e988981d2f5f29cc4 (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe:
"A few fixes for the current series. This contains:
- Two fixes for NVMe:
One fixes a reset race that can be triggered by repeated
insert/removal of the module.
The other fixes an issue on some platforms, where we get probe
timeouts since legacy interrupts isn't working. This used not to
be a problem since we had the worker thread poll for completions,
but since that was killed off, it means those poor souls can't
successfully probe their NVMe device. Use a proper IRQ check and
probe (msi-x -> msi ->legacy), like most other drivers to work
around this. Both from Keith.
- A loop corruption issue with offset in iters, from Ming Lei.
- A fix for not having the partition stat per cpu ref count
initialized before sending out the KOBJ_ADD, which could cause user
space to access the counter prior to initialization. Also from
Ming Lei.
- A fix for using the wrong congestion state, from Kaixu Xia"
* 'for-linus' of git://git.kernel.dk/linux-block:
block: loop: fix filesystem corruption in case of aio/dio
NVMe: Always use MSI/MSI-x interrupts
NVMe: Fix reset/remove race
writeback: fix the wrong congested state variable definition
block: partition: initialize percpuref before sending out KOBJ_ADD
-rw-r--r-- | block/partition-generic.c | 13 | ||||
-rw-r--r-- | drivers/block/loop.c | 6 | ||||
-rw-r--r-- | drivers/nvme/host/pci.c | 31 | ||||
-rw-r--r-- | mm/backing-dev.c | 4 |
4 files changed, 37 insertions, 17 deletions
diff --git a/block/partition-generic.c b/block/partition-generic.c index 2c6ae2aed2c4..d7eb77e1e3a8 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c | |||
@@ -361,15 +361,20 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
361 | goto out_del; | 361 | goto out_del; |
362 | } | 362 | } |
363 | 363 | ||
364 | err = hd_ref_init(p); | ||
365 | if (err) { | ||
366 | if (flags & ADDPART_FLAG_WHOLEDISK) | ||
367 | goto out_remove_file; | ||
368 | goto out_del; | ||
369 | } | ||
370 | |||
364 | /* everything is up and running, commence */ | 371 | /* everything is up and running, commence */ |
365 | rcu_assign_pointer(ptbl->part[partno], p); | 372 | rcu_assign_pointer(ptbl->part[partno], p); |
366 | 373 | ||
367 | /* suppress uevent if the disk suppresses it */ | 374 | /* suppress uevent if the disk suppresses it */ |
368 | if (!dev_get_uevent_suppress(ddev)) | 375 | if (!dev_get_uevent_suppress(ddev)) |
369 | kobject_uevent(&pdev->kobj, KOBJ_ADD); | 376 | kobject_uevent(&pdev->kobj, KOBJ_ADD); |
370 | 377 | return p; | |
371 | if (!hd_ref_init(p)) | ||
372 | return p; | ||
373 | 378 | ||
374 | out_free_info: | 379 | out_free_info: |
375 | free_part_info(p); | 380 | free_part_info(p); |
@@ -378,6 +383,8 @@ out_free_stats: | |||
378 | out_free: | 383 | out_free: |
379 | kfree(p); | 384 | kfree(p); |
380 | return ERR_PTR(err); | 385 | return ERR_PTR(err); |
386 | out_remove_file: | ||
387 | device_remove_file(pdev, &dev_attr_whole_disk); | ||
381 | out_del: | 388 | out_del: |
382 | kobject_put(p->holder_dir); | 389 | kobject_put(p->holder_dir); |
383 | device_del(pdev); | 390 | device_del(pdev); |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 423f4ca7d712..80cf8add46ff 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -488,6 +488,12 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, | |||
488 | bvec = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); | 488 | bvec = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); |
489 | iov_iter_bvec(&iter, ITER_BVEC | rw, bvec, | 489 | iov_iter_bvec(&iter, ITER_BVEC | rw, bvec, |
490 | bio_segments(bio), blk_rq_bytes(cmd->rq)); | 490 | bio_segments(bio), blk_rq_bytes(cmd->rq)); |
491 | /* | ||
492 | * This bio may be started from the middle of the 'bvec' | ||
493 | * because of bio splitting, so offset from the bvec must | ||
494 | * be passed to iov iterator | ||
495 | */ | ||
496 | iter.iov_offset = bio->bi_iter.bi_bvec_done; | ||
491 | 497 | ||
492 | cmd->iocb.ki_pos = pos; | 498 | cmd->iocb.ki_pos = pos; |
493 | cmd->iocb.ki_filp = file; | 499 | cmd->iocb.ki_filp = file; |
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 24ccda303efb..4fd733ff72b1 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
@@ -1478,8 +1478,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) | |||
1478 | if (result > 0) { | 1478 | if (result > 0) { |
1479 | dev_err(dev->ctrl.device, | 1479 | dev_err(dev->ctrl.device, |
1480 | "Could not set queue count (%d)\n", result); | 1480 | "Could not set queue count (%d)\n", result); |
1481 | nr_io_queues = 0; | 1481 | return 0; |
1482 | result = 0; | ||
1483 | } | 1482 | } |
1484 | 1483 | ||
1485 | if (dev->cmb && NVME_CMB_SQS(dev->cmbsz)) { | 1484 | if (dev->cmb && NVME_CMB_SQS(dev->cmbsz)) { |
@@ -1513,7 +1512,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) | |||
1513 | * If we enable msix early due to not intx, disable it again before | 1512 | * If we enable msix early due to not intx, disable it again before |
1514 | * setting up the full range we need. | 1513 | * setting up the full range we need. |
1515 | */ | 1514 | */ |
1516 | if (!pdev->irq) | 1515 | if (pdev->msi_enabled) |
1516 | pci_disable_msi(pdev); | ||
1517 | else if (pdev->msix_enabled) | ||
1517 | pci_disable_msix(pdev); | 1518 | pci_disable_msix(pdev); |
1518 | 1519 | ||
1519 | for (i = 0; i < nr_io_queues; i++) | 1520 | for (i = 0; i < nr_io_queues; i++) |
@@ -1696,7 +1697,6 @@ static int nvme_pci_enable(struct nvme_dev *dev) | |||
1696 | if (pci_enable_device_mem(pdev)) | 1697 | if (pci_enable_device_mem(pdev)) |
1697 | return result; | 1698 | return result; |
1698 | 1699 | ||
1699 | dev->entry[0].vector = pdev->irq; | ||
1700 | pci_set_master(pdev); | 1700 | pci_set_master(pdev); |
1701 | 1701 | ||
1702 | if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) && | 1702 | if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) && |
@@ -1709,13 +1709,18 @@ static int nvme_pci_enable(struct nvme_dev *dev) | |||
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | /* | 1711 | /* |
1712 | * Some devices don't advertse INTx interrupts, pre-enable a single | 1712 | * Some devices and/or platforms don't advertise or work with INTx |
1713 | * MSIX vec for setup. We'll adjust this later. | 1713 | * interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll |
1714 | * adjust this later. | ||
1714 | */ | 1715 | */ |
1715 | if (!pdev->irq) { | 1716 | if (pci_enable_msix(pdev, dev->entry, 1)) { |
1716 | result = pci_enable_msix(pdev, dev->entry, 1); | 1717 | pci_enable_msi(pdev); |
1717 | if (result < 0) | 1718 | dev->entry[0].vector = pdev->irq; |
1718 | goto disable; | 1719 | } |
1720 | |||
1721 | if (!dev->entry[0].vector) { | ||
1722 | result = -ENODEV; | ||
1723 | goto disable; | ||
1719 | } | 1724 | } |
1720 | 1725 | ||
1721 | cap = lo_hi_readq(dev->bar + NVME_REG_CAP); | 1726 | cap = lo_hi_readq(dev->bar + NVME_REG_CAP); |
@@ -1859,6 +1864,9 @@ static void nvme_reset_work(struct work_struct *work) | |||
1859 | if (dev->ctrl.ctrl_config & NVME_CC_ENABLE) | 1864 | if (dev->ctrl.ctrl_config & NVME_CC_ENABLE) |
1860 | nvme_dev_disable(dev, false); | 1865 | nvme_dev_disable(dev, false); |
1861 | 1866 | ||
1867 | if (test_bit(NVME_CTRL_REMOVING, &dev->flags)) | ||
1868 | goto out; | ||
1869 | |||
1862 | set_bit(NVME_CTRL_RESETTING, &dev->flags); | 1870 | set_bit(NVME_CTRL_RESETTING, &dev->flags); |
1863 | 1871 | ||
1864 | result = nvme_pci_enable(dev); | 1872 | result = nvme_pci_enable(dev); |
@@ -2078,11 +2086,10 @@ static void nvme_remove(struct pci_dev *pdev) | |||
2078 | { | 2086 | { |
2079 | struct nvme_dev *dev = pci_get_drvdata(pdev); | 2087 | struct nvme_dev *dev = pci_get_drvdata(pdev); |
2080 | 2088 | ||
2081 | del_timer_sync(&dev->watchdog_timer); | ||
2082 | |||
2083 | set_bit(NVME_CTRL_REMOVING, &dev->flags); | 2089 | set_bit(NVME_CTRL_REMOVING, &dev->flags); |
2084 | pci_set_drvdata(pdev, NULL); | 2090 | pci_set_drvdata(pdev, NULL); |
2085 | flush_work(&dev->async_work); | 2091 | flush_work(&dev->async_work); |
2092 | flush_work(&dev->reset_work); | ||
2086 | flush_work(&dev->scan_work); | 2093 | flush_work(&dev->scan_work); |
2087 | nvme_remove_namespaces(&dev->ctrl); | 2094 | nvme_remove_namespaces(&dev->ctrl); |
2088 | nvme_uninit_ctrl(&dev->ctrl); | 2095 | nvme_uninit_ctrl(&dev->ctrl); |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index bfbd7096b6ed..0c6317b7db38 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -898,7 +898,7 @@ static atomic_t nr_wb_congested[2]; | |||
898 | void clear_wb_congested(struct bdi_writeback_congested *congested, int sync) | 898 | void clear_wb_congested(struct bdi_writeback_congested *congested, int sync) |
899 | { | 899 | { |
900 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | 900 | wait_queue_head_t *wqh = &congestion_wqh[sync]; |
901 | enum wb_state bit; | 901 | enum wb_congested_state bit; |
902 | 902 | ||
903 | bit = sync ? WB_sync_congested : WB_async_congested; | 903 | bit = sync ? WB_sync_congested : WB_async_congested; |
904 | if (test_and_clear_bit(bit, &congested->state)) | 904 | if (test_and_clear_bit(bit, &congested->state)) |
@@ -911,7 +911,7 @@ EXPORT_SYMBOL(clear_wb_congested); | |||
911 | 911 | ||
912 | void set_wb_congested(struct bdi_writeback_congested *congested, int sync) | 912 | void set_wb_congested(struct bdi_writeback_congested *congested, int sync) |
913 | { | 913 | { |
914 | enum wb_state bit; | 914 | enum wb_congested_state bit; |
915 | 915 | ||
916 | bit = sync ? WB_sync_congested : WB_async_congested; | 916 | bit = sync ? WB_sync_congested : WB_async_congested; |
917 | if (!test_and_set_bit(bit, &congested->state)) | 917 | if (!test_and_set_bit(bit, &congested->state)) |