Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3f422c8 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge branch 'nvmf-4.8-rc' of git://git.infradead.org/nvme-fabrics into for-linus

Sagi writes:

Mostly stability fixes for nvmet, rdma:
- fix uninitialized rdma_cm private data from Roland.
- rdma device removal handling (host and target).
- fix controller disconnect during active mounts.
- fix namespaces lost after fabric reconnects.
- remove redundant calls to namespace removal (rdma, loop).
- actually send controller shutdown when disconnecting.
- reconnect fixes (ns rescan and aen requeue)
- nvmet controller serial number inconsistency fix.
parents 29b4817d e3266378
Loading
Loading
Loading
Loading
+45 −38
Original line number Original line Diff line number Diff line
@@ -12,13 +12,11 @@
 * more details.
 * more details.
 */
 */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/jiffies.h>
#include <linux/atomic.h>
#include <linux/atomic.h>
#include <linux/blk-mq.h>
#include <linux/blk-mq.h>
#include <linux/types.h>
#include <linux/types.h>
@@ -26,7 +24,6 @@
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <linux/scatterlist.h>
#include <linux/nvme.h>
#include <linux/nvme.h>
#include <linux/t10-pi.h>
#include <asm/unaligned.h>
#include <asm/unaligned.h>


#include <rdma/ib_verbs.h>
#include <rdma/ib_verbs.h>
@@ -169,7 +166,6 @@ MODULE_PARM_DESC(register_always,
static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
		struct rdma_cm_event *event);
		struct rdma_cm_event *event);
static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl);


/* XXX: really should move to a generic header sooner or later.. */
/* XXX: really should move to a generic header sooner or later.. */
static inline void put_unaligned_le24(u32 val, u8 *p)
static inline void put_unaligned_le24(u32 val, u8 *p)
@@ -687,11 +683,6 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
	list_del(&ctrl->list);
	list_del(&ctrl->list);
	mutex_unlock(&nvme_rdma_ctrl_mutex);
	mutex_unlock(&nvme_rdma_ctrl_mutex);


	if (ctrl->ctrl.tagset) {
		blk_cleanup_queue(ctrl->ctrl.connect_q);
		blk_mq_free_tag_set(&ctrl->tag_set);
		nvme_rdma_dev_put(ctrl->device);
	}
	kfree(ctrl->queues);
	kfree(ctrl->queues);
	nvmf_free_options(nctrl->opts);
	nvmf_free_options(nctrl->opts);
free_ctrl:
free_ctrl:
@@ -748,8 +739,11 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
	changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
	changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
	WARN_ON_ONCE(!changed);
	WARN_ON_ONCE(!changed);


	if (ctrl->queue_count > 1)
	if (ctrl->queue_count > 1) {
		nvme_start_queues(&ctrl->ctrl);
		nvme_start_queues(&ctrl->ctrl);
		nvme_queue_scan(&ctrl->ctrl);
		nvme_queue_async_events(&ctrl->ctrl);
	}


	dev_info(ctrl->ctrl.device, "Successfully reconnected\n");
	dev_info(ctrl->ctrl.device, "Successfully reconnected\n");


@@ -1269,7 +1263,7 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue)
{
{
	struct nvme_rdma_ctrl *ctrl = queue->ctrl;
	struct nvme_rdma_ctrl *ctrl = queue->ctrl;
	struct rdma_conn_param param = { };
	struct rdma_conn_param param = { };
	struct nvme_rdma_cm_req priv;
	struct nvme_rdma_cm_req priv = { };
	int ret;
	int ret;


	param.qp_num = queue->qp->qp_num;
	param.qp_num = queue->qp->qp_num;
@@ -1318,37 +1312,39 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue)
 * that caught the event. Since we hold the callout until the controller
 * that caught the event. Since we hold the callout until the controller
 * deletion is completed, we'll deadlock if the controller deletion will
 * deletion is completed, we'll deadlock if the controller deletion will
 * call rdma_destroy_id on this queue's cm_id. Thus, we claim ownership
 * call rdma_destroy_id on this queue's cm_id. Thus, we claim ownership
 * of destroying this queue before-hand, destroy the queue resources
 * of destroying this queue before-hand, destroy the queue resources,
 * after the controller deletion completed with the exception of destroying
 * then queue the controller deletion which won't destroy this queue and
 * the cm_id implicitely by returning a non-zero rc to the callout.
 * we destroy the cm_id implicitely by returning a non-zero rc to the callout.
 */
 */
static int nvme_rdma_device_unplug(struct nvme_rdma_queue *queue)
static int nvme_rdma_device_unplug(struct nvme_rdma_queue *queue)
{
{
	struct nvme_rdma_ctrl *ctrl = queue->ctrl;
	struct nvme_rdma_ctrl *ctrl = queue->ctrl;
	int ret, ctrl_deleted = 0;
	int ret;


	/* First disable the queue so ctrl delete won't free it */
	/* Own the controller deletion */
	if (!test_and_clear_bit(NVME_RDMA_Q_CONNECTED, &queue->flags))
	if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
		goto out;
		return 0;


	/* delete the controller */
	ret = __nvme_rdma_del_ctrl(ctrl);
	if (!ret) {
	dev_warn(ctrl->ctrl.device,
	dev_warn(ctrl->ctrl.device,
		"Got rdma device removal event, deleting ctrl\n");
		"Got rdma device removal event, deleting ctrl\n");
		flush_work(&ctrl->delete_work);


		/* Return non-zero so the cm_id will destroy implicitly */
	/* Get rid of reconnect work if its running */
		ctrl_deleted = 1;
	cancel_delayed_work_sync(&ctrl->reconnect_work);


	/* Disable the queue so ctrl delete won't free it */
	if (test_and_clear_bit(NVME_RDMA_Q_CONNECTED, &queue->flags)) {
		/* Free this queue ourselves */
		/* Free this queue ourselves */
		rdma_disconnect(queue->cm_id);
		nvme_rdma_stop_queue(queue);
		ib_drain_qp(queue->qp);
		nvme_rdma_destroy_queue_ib(queue);
		nvme_rdma_destroy_queue_ib(queue);

		/* Return non-zero so the cm_id will destroy implicitly */
		ret = 1;
	}
	}


out:
	/* Queue controller deletion */
	return ctrl_deleted;
	queue_work(nvme_rdma_wq, &ctrl->delete_work);
	flush_work(&ctrl->delete_work);
	return ret;
}
}


static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
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)
		nvme_rdma_free_io_queues(ctrl);
		nvme_rdma_free_io_queues(ctrl);
	}
	}


	if (ctrl->ctrl.state == NVME_CTRL_LIVE)
	if (test_bit(NVME_RDMA_Q_CONNECTED, &ctrl->queues[0].flags))
		nvme_shutdown_ctrl(&ctrl->ctrl);
		nvme_shutdown_ctrl(&ctrl->ctrl);


	blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
	blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
@@ -1657,15 +1653,27 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)
	nvme_rdma_destroy_admin_queue(ctrl);
	nvme_rdma_destroy_admin_queue(ctrl);
}
}


static void __nvme_rdma_remove_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
{
	nvme_uninit_ctrl(&ctrl->ctrl);
	if (shutdown)
		nvme_rdma_shutdown_ctrl(ctrl);

	if (ctrl->ctrl.tagset) {
		blk_cleanup_queue(ctrl->ctrl.connect_q);
		blk_mq_free_tag_set(&ctrl->tag_set);
		nvme_rdma_dev_put(ctrl->device);
	}

	nvme_put_ctrl(&ctrl->ctrl);
}

static void nvme_rdma_del_ctrl_work(struct work_struct *work)
static void nvme_rdma_del_ctrl_work(struct work_struct *work)
{
{
	struct nvme_rdma_ctrl *ctrl = container_of(work,
	struct nvme_rdma_ctrl *ctrl = container_of(work,
				struct nvme_rdma_ctrl, delete_work);
				struct nvme_rdma_ctrl, delete_work);


	nvme_remove_namespaces(&ctrl->ctrl);
	__nvme_rdma_remove_ctrl(ctrl, true);
	nvme_rdma_shutdown_ctrl(ctrl);
	nvme_uninit_ctrl(&ctrl->ctrl);
	nvme_put_ctrl(&ctrl->ctrl);
}
}


static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl)
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)
	struct nvme_rdma_ctrl *ctrl = container_of(work,
	struct nvme_rdma_ctrl *ctrl = container_of(work,
				struct nvme_rdma_ctrl, delete_work);
				struct nvme_rdma_ctrl, delete_work);


	nvme_remove_namespaces(&ctrl->ctrl);
	__nvme_rdma_remove_ctrl(ctrl, false);
	nvme_uninit_ctrl(&ctrl->ctrl);
	nvme_put_ctrl(&ctrl->ctrl);
}
}


static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
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)
	if (ctrl->queue_count > 1) {
	if (ctrl->queue_count > 1) {
		nvme_start_queues(&ctrl->ctrl);
		nvme_start_queues(&ctrl->ctrl);
		nvme_queue_scan(&ctrl->ctrl);
		nvme_queue_scan(&ctrl->ctrl);
		nvme_queue_async_events(&ctrl->ctrl);
	}
	}


	return;
	return;
+1 −5
Original line number Original line Diff line number Diff line
@@ -13,7 +13,6 @@
 */
 */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/module.h>
#include <linux/random.h>
#include <generated/utsrelease.h>
#include <generated/utsrelease.h>
#include "nvmet.h"
#include "nvmet.h"


@@ -83,7 +82,6 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
{
{
	struct nvmet_ctrl *ctrl = req->sq->ctrl;
	struct nvmet_ctrl *ctrl = req->sq->ctrl;
	struct nvme_id_ctrl *id;
	struct nvme_id_ctrl *id;
	u64 serial;
	u16 status = 0;
	u16 status = 0;


	id = kzalloc(sizeof(*id), GFP_KERNEL);
	id = kzalloc(sizeof(*id), GFP_KERNEL);
@@ -96,10 +94,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
	id->vid = 0;
	id->vid = 0;
	id->ssvid = 0;
	id->ssvid = 0;


	/* generate a random serial number as our controllers are ephemeral: */
	get_random_bytes(&serial, sizeof(serial));
	memset(id->sn, ' ', sizeof(id->sn));
	memset(id->sn, ' ', sizeof(id->sn));
	snprintf(id->sn, sizeof(id->sn), "%llx", serial);
	snprintf(id->sn, sizeof(id->sn), "%llx", ctrl->serial);


	memset(id->mn, ' ', sizeof(id->mn));
	memset(id->mn, ' ', sizeof(id->mn));
	strncpy((char *)id->mn, "Linux", sizeof(id->mn));
	strncpy((char *)id->mn, "Linux", sizeof(id->mn));
+4 −0
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@
 */
 */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/module.h>
#include <linux/random.h>
#include "nvmet.h"
#include "nvmet.h"


static struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX];
static struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX];
@@ -728,6 +729,9 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
	memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE);
	memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE);
	memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE);
	memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE);


	/* generate a random serial number as our controllers are ephemeral: */
	get_random_bytes(&ctrl->serial, sizeof(ctrl->serial));

	kref_init(&ctrl->ref);
	kref_init(&ctrl->ref);
	ctrl->subsys = subsys;
	ctrl->subsys = subsys;


+1 −3
Original line number Original line Diff line number Diff line
@@ -414,9 +414,8 @@ static void nvme_loop_del_ctrl_work(struct work_struct *work)
	struct nvme_loop_ctrl *ctrl = container_of(work,
	struct nvme_loop_ctrl *ctrl = container_of(work,
				struct nvme_loop_ctrl, delete_work);
				struct nvme_loop_ctrl, delete_work);


	nvme_remove_namespaces(&ctrl->ctrl);
	nvme_loop_shutdown_ctrl(ctrl);
	nvme_uninit_ctrl(&ctrl->ctrl);
	nvme_uninit_ctrl(&ctrl->ctrl);
	nvme_loop_shutdown_ctrl(ctrl);
	nvme_put_ctrl(&ctrl->ctrl);
	nvme_put_ctrl(&ctrl->ctrl);
}
}


@@ -501,7 +500,6 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)
	nvme_loop_destroy_admin_queue(ctrl);
	nvme_loop_destroy_admin_queue(ctrl);
out_disable:
out_disable:
	dev_warn(ctrl->ctrl.device, "Removing after reset failure\n");
	dev_warn(ctrl->ctrl.device, "Removing after reset failure\n");
	nvme_remove_namespaces(&ctrl->ctrl);
	nvme_uninit_ctrl(&ctrl->ctrl);
	nvme_uninit_ctrl(&ctrl->ctrl);
	nvme_put_ctrl(&ctrl->ctrl);
	nvme_put_ctrl(&ctrl->ctrl);
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -113,6 +113,7 @@ struct nvmet_ctrl {


	struct mutex		lock;
	struct mutex		lock;
	u64			cap;
	u64			cap;
	u64			serial;
	u32			cc;
	u32			cc;
	u32			csts;
	u32			csts;


Loading