Pull block fixes from Jens Axboe: - an NVMe fix from Gabriel, fixing a suspend/resume issue on some setups - addition of a few missing entries in the block queue sysfs documentation, from Joe - a fix for a sparse shadow warning for the bvec iterator, from Johannes - a writeback deadlock involving raid issuing barriers, and not flushing the plug when we wakeup the flusher threads. From Konstantin - a set of patches for the NVMe target/loop/rdma code, from Roland and Sagi * 'for-linus' of git://git.kernel.dk/linux-block: bvec: avoid variable shadowing warning doc: update block/queue-sysfs.txt entries nvme: Suspend all queues before deletion mm, writeback: flush plugged IO in wakeup_flusher_threads() nvme-rdma: Remove unused includes nvme-rdma: start async event handler after reconnecting to a controller nvmet: Fix controller serial number inconsistency nvmet-rdma: Don't use the inline buffer in order to avoid allocation for small reads nvmet-rdma: Correctly handle RDMA device hot removal nvme-rdma: Make sure to shutdown the controller if we can nvme-loop: Remove duplicate call to nvme_remove_namespaces nvme-rdma: Free the I/O tags when we delete the controller nvme-rdma: Remove duplicate call to nvme_remove_namespaces nvme-rdma: Fix device removal handling nvme-rdma: Queue ns scanning after a sucessful reconnection nvme-rdma: Don't leak uninitialized memory in connect request private data
Unified · Split
| @@ -14,6 +14,12 @@ add_random (RW) · 13 unmodified lines | ||
| 14 | 14 | This file allows to turn off the disk entropy contribution. Default |
| 15 | 15 | value of this file is '1'(on). |
| 16 | 16 | |
| 17 | +dax (RO) | |
| 18 | +-------- | |
| 19 | +This file indicates whether the device supports Direct Access (DAX), | |
| 20 | +used by CPU-addressable storage to bypass the pagecache. It shows '1' | |
| 21 | +if true, '0' if not. | |
| 22 | + | |
| 17 | 23 | discard_granularity (RO) |
| 18 | 24 | ----------------------- |
| 19 | 25 | This shows the size of internal allocation of the device in bytes, if |
| @@ -46,6 +52,12 @@ hw_sector_size (RO) · 26 unmodified lines | ||
| 46 | 52 | ------------------- |
| 47 | 53 | This is the hardware sector size of the device, in bytes. |
| 48 | 54 | |
| 55 | +io_poll (RW) | |
| 56 | +------------ | |
| 57 | +When read, this file shows the total number of block IO polls and how | |
| 58 | +many returned success. Writing '0' to this file will disable polling | |
| 59 | +for this device. Writing any non-zero value will enable this feature. | |
| 60 | + | |
| 49 | 61 | iostats (RW) |
| 50 | 62 | ------------- |
| 51 | 63 | This file is used to control (on/off) the iostats accounting of the |
| @@ -151,5 +163,11 @@ device state. This means that it might not be safe to toggle the · 99 unmodified lines | ||
| 151 | 163 | setting from "write back" to "write through", since that will also |
| 152 | 164 | eliminate cache flushes issued by the kernel. |
| 153 | 165 | |
| 166 | +write_same_max_bytes (RO) | |
| 167 | +------------------------- | |
| 168 | +This is the number of bytes the device can write in a single write-same | |
| 169 | +command. A value of '0' means write-same is not supported by this | |
| 170 | +device. | |
| 171 | + | |
| 154 | 172 | |
| 155 | 173 | Jens Axboe <jens.axboe@oracle.com>, February 2009 |
| @@ -1543,15 +1543,10 @@ static void nvme_disable_io_queues(struct nvme_dev *dev) · 1542 unmodified lines | ||
| 1543 | 1543 | reinit_completion(&dev->ioq_wait); |
| 1544 | 1544 | retry: |
| 1545 | 1545 | timeout = ADMIN_TIMEOUT; |
| 1546 | − for (; i > 0; i--) { | |
| 1547 | − struct nvme_queue *nvmeq = dev->queues[i]; | |
| 1548 | − | |
| 1549 | − if (!pass) | |
| 1550 | − nvme_suspend_queue(nvmeq); | |
| 1551 | − if (nvme_delete_queue(nvmeq, opcode)) | |
| 1546 | + for (; i > 0; i--, sent++) | |
| 1547 | + if (nvme_delete_queue(dev->queues[i], opcode)) | |
| 1552 | 1548 | break; |
| 1553 | − ++sent; | |
| 1554 | − } | |
| 1549 | + | |
| 1555 | 1550 | while (sent--) { |
| 1556 | 1551 | timeout = wait_for_completion_io_timeout(&dev->ioq_wait, timeout); |
| 1557 | 1552 | if (timeout == 0) |
| @@ -1693,11 +1688,12 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) · 135 unmodified lines | ||
| 1693 | 1688 | nvme_stop_queues(&dev->ctrl); |
| 1694 | 1689 | csts = readl(dev->bar + NVME_REG_CSTS); |
| 1695 | 1690 | } |
| 1691 | + | |
| 1692 | + for (i = dev->queue_count - 1; i > 0; i--) | |
| 1693 | + nvme_suspend_queue(dev->queues[i]); | |
| 1694 | + | |
| 1696 | 1695 | if (csts & NVME_CSTS_CFS || !(csts & NVME_CSTS_RDY)) { |
| 1697 | − for (i = dev->queue_count - 1; i >= 0; i--) { | |
| 1698 | − struct nvme_queue *nvmeq = dev->queues[i]; | |
| 1699 | − nvme_suspend_queue(nvmeq); | |
| 1700 | − } | |
| 1696 | + nvme_suspend_queue(dev->queues[0]); | |
| 1701 | 1697 | } else { |
| 1702 | 1698 | nvme_disable_io_queues(dev); |
| 1703 | 1699 | nvme_disable_admin_queue(dev, shutdown); |
| @@ -12,13 +12,11 @@ · 11 unmodified lines | ||
| 12 | 12 | * more details. |
| 13 | 13 | */ |
| 14 | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 15 | −#include <linux/delay.h> | |
| 16 | 15 | #include <linux/module.h> |
| 17 | 16 | #include <linux/init.h> |
| 18 | 17 | #include <linux/slab.h> |
| 19 | 18 | #include <linux/err.h> |
| 20 | 19 | #include <linux/string.h> |
| 21 | −#include <linux/jiffies.h> | |
| 22 | 20 | #include <linux/atomic.h> |
| 23 | 21 | #include <linux/blk-mq.h> |
| 24 | 22 | #include <linux/types.h> |
| @@ -26,7 +24,6 @@ · 1 unmodified line | ||
| 26 | 24 | #include <linux/mutex.h> |
| 27 | 25 | #include <linux/scatterlist.h> |
| 28 | 26 | #include <linux/nvme.h> |
| 29 | −#include <linux/t10-pi.h> | |
| 30 | 27 | #include <asm/unaligned.h> |
| 31 | 28 | |
| 32 | 29 | #include <rdma/ib_verbs.h> |
| @@ -169,7 +166,6 @@ MODULE_PARM_DESC(register_always, · 136 unmodified lines | ||
| 169 | 166 | static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, |
| 170 | 167 | struct rdma_cm_event *event); |
| 171 | 168 | static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc); |
| 172 | −static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl); | |
| 173 | 169 | |
| 174 | 170 | /* XXX: really should move to a generic header sooner or later.. */ |
| 175 | 171 | static inline void put_unaligned_le24(u32 val, u8 *p) |
| @@ -687,11 +683,6 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl) · 511 unmodified lines | ||
| 687 | 683 | list_del(&ctrl->list); |
| 688 | 684 | mutex_unlock(&nvme_rdma_ctrl_mutex); |
| 689 | 685 | |
| 690 | − if (ctrl->ctrl.tagset) { | |
| 691 | − blk_cleanup_queue(ctrl->ctrl.connect_q); | |
| 692 | − blk_mq_free_tag_set(&ctrl->tag_set); | |
| 693 | − nvme_rdma_dev_put(ctrl->device); | |
| 694 | − } | |
| 695 | 686 | kfree(ctrl->queues); |
| 696 | 687 | nvmf_free_options(nctrl->opts); |
| 697 | 688 | free_ctrl: |
| @@ -748,8 +739,11 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) · 50 unmodified lines | ||
| 748 | 739 | changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); |
| 749 | 740 | WARN_ON_ONCE(!changed); |
| 750 | 741 | |
| 751 | − if (ctrl->queue_count > 1) | |
| 742 | + if (ctrl->queue_count > 1) { | |
| 752 | 743 | nvme_start_queues(&ctrl->ctrl); |
| 744 | + nvme_queue_scan(&ctrl->ctrl); | |
| 745 | + nvme_queue_async_events(&ctrl->ctrl); | |
| 746 | + } | |
| 753 | 747 | |
| 754 | 748 | dev_info(ctrl->ctrl.device, "Successfully reconnected\n"); |
| 755 | 749 | |
| @@ -1269,7 +1263,7 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue) · 513 unmodified lines | ||
| 1269 | 1263 | { |
| 1270 | 1264 | struct nvme_rdma_ctrl *ctrl = queue->ctrl; |
| 1271 | 1265 | struct rdma_conn_param param = { }; |
| 1272 | − struct nvme_rdma_cm_req priv; | |
| 1266 | + struct nvme_rdma_cm_req priv = { }; | |
| 1273 | 1267 | int ret; |
| 1274 | 1268 | |
| 1275 | 1269 | param.qp_num = queue->qp->qp_num; |
| @@ -1318,37 +1312,39 @@ out_destroy_queue_ib: · 42 unmodified lines | ||
| 1318 | 1312 | * that caught the event. Since we hold the callout until the controller |
| 1319 | 1313 | * deletion is completed, we'll deadlock if the controller deletion will |
| 1320 | 1314 | * call rdma_destroy_id on this queue's cm_id. Thus, we claim ownership |
| 1321 | − * of destroying this queue before-hand, destroy the queue resources | |
| 1322 | − * after the controller deletion completed with the exception of destroying | |
| 1323 | − * the cm_id implicitely by returning a non-zero rc to the callout. | |
| 1315 | + * of destroying this queue before-hand, destroy the queue resources, | |
| 1316 | + * then queue the controller deletion which won't destroy this queue and | |
| 1317 | + * we destroy the cm_id implicitely by returning a non-zero rc to the callout. | |
| 1324 | 1318 | */ |
| 1325 | 1319 | static int nvme_rdma_device_unplug(struct nvme_rdma_queue *queue) |
| 1326 | 1320 | { |
| 1327 | 1321 | struct nvme_rdma_ctrl *ctrl = queue->ctrl; |
| 1328 | − int ret, ctrl_deleted = 0; | |
| 1322 | + int ret; | |
| 1329 | 1323 | |
| 1330 | − /* First disable the queue so ctrl delete won't free it */ | |
| 1331 | − if (!test_and_clear_bit(NVME_RDMA_Q_CONNECTED, &queue->flags)) | |
| 1332 | − goto out; | |
| 1324 | + /* Own the controller deletion */ | |
| 1325 | + if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING)) | |
| 1326 | + return 0; | |
| 1333 | 1327 | |
| 1334 | − /* delete the controller */ | |
| 1335 | − ret = __nvme_rdma_del_ctrl(ctrl); | |
| 1336 | − if (!ret) { | |
| 1337 | − dev_warn(ctrl->ctrl.device, | |
| 1338 | − "Got rdma device removal event, deleting ctrl\n"); | |
| 1339 | − flush_work(&ctrl->delete_work); | |
| 1328 | + dev_warn(ctrl->ctrl.device, | |
| 1329 | + "Got rdma device removal event, deleting ctrl\n"); | |
| 1340 | 1330 | |
| 1341 | − /* Return non-zero so the cm_id will destroy implicitly */ | |
| 1342 | − ctrl_deleted = 1; | |
| 1331 | + /* Get rid of reconnect work if its running */ | |
| 1332 | + cancel_delayed_work_sync(&ctrl->reconnect_work); | |
| 1343 | 1333 | |
| 1334 | + /* Disable the queue so ctrl delete won't free it */ | |
| 1335 | + if (test_and_clear_bit(NVME_RDMA_Q_CONNECTED, &queue->flags)) { | |
| 1344 | 1336 | /* Free this queue ourselves */ |
| 1345 | − rdma_disconnect(queue->cm_id); | |
| 1346 | − ib_drain_qp(queue->qp); | |
| 1337 | + nvme_rdma_stop_queue(queue); | |
| 1347 | 1338 | nvme_rdma_destroy_queue_ib(queue); |
| 1339 | + | |
| 1340 | + /* Return non-zero so the cm_id will destroy implicitly */ | |
| 1341 | + ret = 1; | |
| 1348 | 1342 | } |
| 1349 | 1343 | |
| 1350 | −out: | |
| 1351 | − return ctrl_deleted; | |
| 1344 | + /* Queue controller deletion */ | |
| 1345 | + queue_work(nvme_rdma_wq, &ctrl->delete_work); | |
| 1346 | + flush_work(&ctrl->delete_work); | |
| 1347 | + return ret; | |
| 1352 | 1348 | } |
| 1353 | 1349 | |
| 1354 | 1350 | static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, |
| @@ -1648,7 +1644,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl) · 293 unmodified lines | ||
| 1648 | 1644 | nvme_rdma_free_io_queues(ctrl); |
| 1649 | 1645 | } |
| 1650 | 1646 | |
| 1651 | − if (ctrl->ctrl.state == NVME_CTRL_LIVE) | |
| 1647 | + if (test_bit(NVME_RDMA_Q_CONNECTED, &ctrl->queues[0].flags)) | |
| 1652 | 1648 | nvme_shutdown_ctrl(&ctrl->ctrl); |
| 1653 | 1649 | |
| 1654 | 1650 | blk_mq_stop_hw_queues(ctrl->ctrl.admin_q); |
| @@ -1657,15 +1653,27 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl) · 2 unmodified lines | ||
| 1657 | 1653 | nvme_rdma_destroy_admin_queue(ctrl); |
| 1658 | 1654 | } |
| 1659 | 1655 | |
| 1656 | +static void __nvme_rdma_remove_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown) | |
| 1657 | +{ | |
| 1658 | + nvme_uninit_ctrl(&ctrl->ctrl); | |
| 1659 | + if (shutdown) | |
| 1660 | + nvme_rdma_shutdown_ctrl(ctrl); | |
| 1661 | + | |
| 1662 | + if (ctrl->ctrl.tagset) { | |
| 1663 | + blk_cleanup_queue(ctrl->ctrl.connect_q); | |
| 1664 | + blk_mq_free_tag_set(&ctrl->tag_set); | |
| 1665 | + nvme_rdma_dev_put(ctrl->device); | |
| 1666 | + } | |
| 1667 | + | |
| 1668 | + nvme_put_ctrl(&ctrl->ctrl); | |
| 1669 | +} | |
| 1670 | + | |
| 1660 | 1671 | static void nvme_rdma_del_ctrl_work(struct work_struct *work) |
| 1661 | 1672 | { |
| 1662 | 1673 | struct nvme_rdma_ctrl *ctrl = container_of(work, |
| 1663 | 1674 | struct nvme_rdma_ctrl, delete_work); |
| 1664 | 1675 | |
| 1665 | − nvme_remove_namespaces(&ctrl->ctrl); | |
| 1666 | − nvme_rdma_shutdown_ctrl(ctrl); | |
| 1667 | − nvme_uninit_ctrl(&ctrl->ctrl); | |
| 1668 | − nvme_put_ctrl(&ctrl->ctrl); | |
| 1676 | + __nvme_rdma_remove_ctrl(ctrl, true); | |
| 1669 | 1677 | } |
| 1670 | 1678 | |
| 1671 | 1679 | static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl) |
| @@ -1698,9 +1706,7 @@ static void nvme_rdma_remove_ctrl_work(struct work_struct *work) · 26 unmodified lines | ||
| 1698 | 1706 | struct nvme_rdma_ctrl *ctrl = container_of(work, |
| 1699 | 1707 | struct nvme_rdma_ctrl, delete_work); |
| 1700 | 1708 | |
| 1701 | − nvme_remove_namespaces(&ctrl->ctrl); | |
| 1702 | − nvme_uninit_ctrl(&ctrl->ctrl); | |
| 1703 | − nvme_put_ctrl(&ctrl->ctrl); | |
| 1709 | + __nvme_rdma_remove_ctrl(ctrl, false); | |
| 1704 | 1710 | } |
| 1705 | 1711 | |
| 1706 | 1712 | static void nvme_rdma_reset_ctrl_work(struct work_struct *work) |
| @@ -1739,6 +1745,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work) · 32 unmodified lines | ||
| 1739 | 1745 | if (ctrl->queue_count > 1) { |
| 1740 | 1746 | nvme_start_queues(&ctrl->ctrl); |
| 1741 | 1747 | nvme_queue_scan(&ctrl->ctrl); |
| 1748 | + nvme_queue_async_events(&ctrl->ctrl); | |
| 1742 | 1749 | } |
| 1743 | 1750 | |
| 1744 | 1751 | return; |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 15 | 15 | #include <linux/module.h> |
| 16 | −#include <linux/random.h> | |
| 17 | 16 | #include <generated/utsrelease.h> |
| 18 | 17 | #include "nvmet.h" |
| 19 | 18 | |
| @@ -83,7 +82,6 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req) · 63 unmodified lines | ||
| 83 | 82 | { |
| 84 | 83 | struct nvmet_ctrl *ctrl = req->sq->ctrl; |
| 85 | 84 | struct nvme_id_ctrl *id; |
| 86 | − u64 serial; | |
| 87 | 85 | u16 status = 0; |
| 88 | 86 | |
| 89 | 87 | id = kzalloc(sizeof(*id), GFP_KERNEL); |
| @@ -96,10 +94,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req) · 6 unmodified lines | ||
| 96 | 94 | id->vid = 0; |
| 97 | 95 | id->ssvid = 0; |
| 98 | 96 | |
| 99 | − /* generate a random serial number as our controllers are ephemeral: */ | |
| 100 | − get_random_bytes(&serial, sizeof(serial)); | |
| 101 | 97 | memset(id->sn, ' ', sizeof(id->sn)); |
| 102 | − snprintf(id->sn, sizeof(id->sn), "%llx", serial); | |
| 98 | + snprintf(id->sn, sizeof(id->sn), "%llx", ctrl->serial); | |
| 103 | 99 | |
| 104 | 100 | memset(id->mn, ' ', sizeof(id->mn)); |
| 105 | 101 | strncpy((char *)id->mn, "Linux", sizeof(id->mn)); |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 15 | 15 | #include <linux/module.h> |
| 16 | +#include <linux/random.h> | |
| 16 | 17 | #include "nvmet.h" |
| 17 | 18 | |
| 18 | 19 | static struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX]; |
| @@ -728,6 +729,9 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, · 709 unmodified lines | ||
| 728 | 729 | memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE); |
| 729 | 730 | memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE); |
| 730 | 731 | |
| 732 | + /* generate a random serial number as our controllers are ephemeral: */ | |
| 733 | + get_random_bytes(&ctrl->serial, sizeof(ctrl->serial)); | |
| 734 | + | |
| 731 | 735 | kref_init(&ctrl->ref); |
| 732 | 736 | ctrl->subsys = subsys; |
| 733 | 737 | |
| @@ -414,9 +414,8 @@ static void nvme_loop_del_ctrl_work(struct work_struct *work) · 413 unmodified lines | ||
| 414 | 414 | struct nvme_loop_ctrl *ctrl = container_of(work, |
| 415 | 415 | struct nvme_loop_ctrl, delete_work); |
| 416 | 416 | |
| 417 | − nvme_remove_namespaces(&ctrl->ctrl); | |
| 418 | − nvme_loop_shutdown_ctrl(ctrl); | |
| 419 | 417 | nvme_uninit_ctrl(&ctrl->ctrl); |
| 418 | + nvme_loop_shutdown_ctrl(ctrl); | |
| 420 | 419 | nvme_put_ctrl(&ctrl->ctrl); |
| 421 | 420 | } |
| 422 | 421 | |
| @@ -501,7 +500,6 @@ out_free_queues: · 78 unmodified lines | ||
| 501 | 500 | nvme_loop_destroy_admin_queue(ctrl); |
| 502 | 501 | out_disable: |
| 503 | 502 | dev_warn(ctrl->ctrl.device, "Removing after reset failure\n"); |
| 504 | − nvme_remove_namespaces(&ctrl->ctrl); | |
| 505 | 503 | nvme_uninit_ctrl(&ctrl->ctrl); |
| 506 | 504 | nvme_put_ctrl(&ctrl->ctrl); |
| 507 | 505 | } |
| @@ -113,6 +113,7 @@ struct nvmet_ctrl { · 112 unmodified lines | ||
| 113 | 113 | |
| 114 | 114 | struct mutex lock; |
| 115 | 115 | u64 cap; |
| 116 | + u64 serial; | |
| 116 | 117 | u32 cc; |
| 117 | 118 | u32 csts; |
| 118 | 119 | |
| @@ -77,6 +77,7 @@ enum nvmet_rdma_queue_state { · 76 unmodified lines | ||
| 77 | 77 | NVMET_RDMA_Q_CONNECTING, |
| 78 | 78 | NVMET_RDMA_Q_LIVE, |
| 79 | 79 | NVMET_RDMA_Q_DISCONNECTING, |
| 80 | + NVMET_RDMA_IN_DEVICE_REMOVAL, | |
| 80 | 81 | }; |
| 81 | 82 | |
| 82 | 83 | struct nvmet_rdma_queue { |
| @@ -615,15 +616,10 @@ static u16 nvmet_rdma_map_sgl_keyed(struct nvmet_rdma_rsp *rsp, · 532 unmodified lines | ||
| 615 | 616 | if (!len) |
| 616 | 617 | return 0; |
| 617 | 618 | |
| 618 | − /* use the already allocated data buffer if possible */ | |
| 619 | − if (len <= NVMET_RDMA_INLINE_DATA_SIZE && rsp->queue->host_qid) { | |
| 620 | − nvmet_rdma_use_inline_sg(rsp, len, 0); | |
| 621 | − } else { | |
| 622 | − status = nvmet_rdma_alloc_sgl(&rsp->req.sg, &rsp->req.sg_cnt, | |
| 623 | − len); | |
| 624 | − if (status) | |
| 625 | − return status; | |
| 626 | − } | |
| 619 | + status = nvmet_rdma_alloc_sgl(&rsp->req.sg, &rsp->req.sg_cnt, | |
| 620 | + len); | |
| 621 | + if (status) | |
| 622 | + return status; | |
| 627 | 623 | |
| 628 | 624 | ret = rdma_rw_ctx_init(&rsp->rw, cm_id->qp, cm_id->port_num, |
| 629 | 625 | rsp->req.sg, rsp->req.sg_cnt, 0, addr, key, |
| @@ -984,7 +980,10 @@ static void nvmet_rdma_release_queue_work(struct work_struct *w) · 354 unmodified lines | ||
| 984 | 980 | struct nvmet_rdma_device *dev = queue->dev; |
| 985 | 981 | |
| 986 | 982 | nvmet_rdma_free_queue(queue); |
| 987 | − rdma_destroy_id(cm_id); | |
| 983 | + | |
| 984 | + if (queue->state != NVMET_RDMA_IN_DEVICE_REMOVAL) | |
| 985 | + rdma_destroy_id(cm_id); | |
| 986 | + | |
| 988 | 987 | kref_put(&dev->ref, nvmet_rdma_free_dev); |
| 989 | 988 | } |
| 990 | 989 | |
| @@ -1233,8 +1232,9 @@ static void __nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue) · 242 unmodified lines | ||
| 1233 | 1232 | switch (queue->state) { |
| 1234 | 1233 | case NVMET_RDMA_Q_CONNECTING: |
| 1235 | 1234 | case NVMET_RDMA_Q_LIVE: |
| 1236 | − disconnect = true; | |
| 1237 | 1235 | queue->state = NVMET_RDMA_Q_DISCONNECTING; |
| 1236 | + case NVMET_RDMA_IN_DEVICE_REMOVAL: | |
| 1237 | + disconnect = true; | |
| 1238 | 1238 | break; |
| 1239 | 1239 | case NVMET_RDMA_Q_DISCONNECTING: |
| 1240 | 1240 | break; |
| @@ -1272,6 +1272,62 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id, · 31 unmodified lines | ||
| 1272 | 1272 | schedule_work(&queue->release_work); |
| 1273 | 1273 | } |
| 1274 | 1274 | |
| 1275 | +/** | |
| 1276 | + * nvme_rdma_device_removal() - Handle RDMA device removal | |
| 1277 | + * @queue: nvmet rdma queue (cm id qp_context) | |
| 1278 | + * @addr: nvmet address (cm_id context) | |
| 1279 | + * | |
| 1280 | + * DEVICE_REMOVAL event notifies us that the RDMA device is about | |
| 1281 | + * to unplug so we should take care of destroying our RDMA resources. | |
| 1282 | + * This event will be generated for each allocated cm_id. | |
| 1283 | + * | |
| 1284 | + * Note that this event can be generated on a normal queue cm_id | |
| 1285 | + * and/or a device bound listener cm_id (where in this case | |
| 1286 | + * queue will be null). | |
| 1287 | + * | |
| 1288 | + * we claim ownership on destroying the cm_id. For queues we move | |
| 1289 | + * the queue state to NVMET_RDMA_IN_DEVICE_REMOVAL and for port | |
| 1290 | + * we nullify the priv to prevent double cm_id destruction and destroying | |
| 1291 | + * the cm_id implicitely by returning a non-zero rc to the callout. | |
| 1292 | + */ | |
| 1293 | +static int nvmet_rdma_device_removal(struct rdma_cm_id *cm_id, | |
| 1294 | + struct nvmet_rdma_queue *queue) | |
| 1295 | +{ | |
| 1296 | + unsigned long flags; | |
| 1297 | + | |
| 1298 | + if (!queue) { | |
| 1299 | + struct nvmet_port *port = cm_id->context; | |
| 1300 | + | |
| 1301 | + /* | |
| 1302 | + * This is a listener cm_id. Make sure that | |
| 1303 | + * future remove_port won't invoke a double | |
| 1304 | + * cm_id destroy. use atomic xchg to make sure | |
| 1305 | + * we don't compete with remove_port. | |
| 1306 | + */ | |
| 1307 | + if (xchg(&port->priv, NULL) != cm_id) | |
| 1308 | + return 0; | |
| 1309 | + } else { | |
| 1310 | + /* | |
| 1311 | + * This is a queue cm_id. Make sure that | |
| 1312 | + * release queue will not destroy the cm_id | |
| 1313 | + * and schedule all ctrl queues removal (only | |
| 1314 | + * if the queue is not disconnecting already). | |
| 1315 | + */ | |
| 1316 | + spin_lock_irqsave(&queue->state_lock, flags); | |
| 1317 | + if (queue->state != NVMET_RDMA_Q_DISCONNECTING) | |
| 1318 | + queue->state = NVMET_RDMA_IN_DEVICE_REMOVAL; | |
| 1319 | + spin_unlock_irqrestore(&queue->state_lock, flags); | |
| 1320 | + nvmet_rdma_queue_disconnect(queue); | |
| 1321 | + flush_scheduled_work(); | |
| 1322 | + } | |
| 1323 | + | |
| 1324 | + /* | |
| 1325 | + * We need to return 1 so that the core will destroy | |
| 1326 | + * it's own ID. What a great API design.. | |
| 1327 | + */ | |
| 1328 | + return 1; | |
| 1329 | +} | |
| 1330 | + | |
| 1275 | 1331 | static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id, |
| 1276 | 1332 | struct rdma_cm_event *event) |
| 1277 | 1333 | { |
| @@ -1294,20 +1350,11 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id, · 16 unmodified lines | ||
| 1294 | 1350 | break; |
| 1295 | 1351 | case RDMA_CM_EVENT_ADDR_CHANGE: |
| 1296 | 1352 | case RDMA_CM_EVENT_DISCONNECTED: |
| 1297 | − case RDMA_CM_EVENT_DEVICE_REMOVAL: | |
| 1298 | 1353 | case RDMA_CM_EVENT_TIMEWAIT_EXIT: |
| 1299 | − /* | |
| 1300 | − * We can get the device removal callback even for a | |
| 1301 | − * CM ID that we aren't actually using. In that case | |
| 1302 | − * the context pointer is NULL, so we shouldn't try | |
| 1303 | − * to disconnect a non-existing queue. But we also | |
| 1304 | − * need to return 1 so that the core will destroy | |
| 1305 | − * it's own ID. What a great API design.. | |
| 1306 | − */ | |
| 1307 | − if (queue) | |
| 1308 | − nvmet_rdma_queue_disconnect(queue); | |
| 1309 | − else | |
| 1310 | − ret = 1; | |
| 1354 | + nvmet_rdma_queue_disconnect(queue); | |
| 1355 | + break; | |
| 1356 | + case RDMA_CM_EVENT_DEVICE_REMOVAL: | |
| 1357 | + ret = nvmet_rdma_device_removal(cm_id, queue); | |
| 1311 | 1358 | break; |
| 1312 | 1359 | case RDMA_CM_EVENT_REJECTED: |
| 1313 | 1360 | case RDMA_CM_EVENT_UNREACHABLE: |
| @@ -1396,9 +1443,10 @@ out_destroy_id: · 82 unmodified lines | ||
| 1396 | 1443 | |
| 1397 | 1444 | static void nvmet_rdma_remove_port(struct nvmet_port *port) |
| 1398 | 1445 | { |
| 1399 | − struct rdma_cm_id *cm_id = port->priv; | |
| 1446 | + struct rdma_cm_id *cm_id = xchg(&port->priv, NULL); | |
| 1400 | 1447 | |
| 1401 | − rdma_destroy_id(cm_id); | |
| 1448 | + if (cm_id) | |
| 1449 | + rdma_destroy_id(cm_id); | |
| 1402 | 1450 | } |
| 1403 | 1451 | |
| 1404 | 1452 | static struct nvmet_fabrics_ops nvmet_rdma_ops = { |
| @@ -1949,6 +1949,12 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason) · 1948 unmodified lines | ||
| 1949 | 1949 | { |
| 1950 | 1950 | struct backing_dev_info *bdi; |
| 1951 | 1951 | |
| 1952 | + /* | |
| 1953 | + * If we are expecting writeback progress we must submit plugged IO. | |
| 1954 | + */ | |
| 1955 | + if (blk_needs_flush_plug(current)) | |
| 1956 | + blk_schedule_flush_plug(current); | |
| 1957 | + | |
| 1952 | 1958 | if (!nr_pages) |
| 1953 | 1959 | nr_pages = get_nr_dirty_pages(); |
| 1954 | 1960 | |
| @@ -74,7 +74,8 @@ static inline void bvec_iter_advance(const struct bio_vec *bv, · 73 unmodified lines | ||
| 74 | 74 | "Attempted to advance past end of bvec iter\n"); |
| 75 | 75 | |
| 76 | 76 | while (bytes) { |
| 77 | − unsigned len = min(bytes, bvec_iter_len(bv, *iter)); | |
| 77 | + unsigned iter_len = bvec_iter_len(bv, *iter); | |
| 78 | + unsigned len = min(bytes, iter_len); | |
| 78 | 79 | |
| 79 | 80 | bytes -= len; |
| 80 | 81 | iter->bi_size -= len; |