Commit 1e06b3e7 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'nvme-5.18-2022-03-29' of git://git.infradead.org/nvme into for-5.18/drivers

Pull NVMe fixes from Christoph:

"- fix multipath hang when disk goes live over reconnect (Anton Eidelman)
 - fix RCU hole that allowed for endless looping in multipath round robin
   (Chris Leech)
 - remove redundant assignment after left shift (Colin Ian King)
 - add quirks for Samsung X5 SSDs (Monish Kumar R)
 - fix the read-only state for zoned namespaces with unsupposed features
   (Pankaj Raghav)
 - use a private workqueue instead of the system workqueue in nvmet
   (Sagi Grimberg)
 - allow duplicate NSIDs for private namespaces (Sungup Moon)
 - expose use_threaded_interrupts read-only in sysfs (Xin Hao)"

* tag 'nvme-5.18-2022-03-29' of git://git.infradead.org/nvme:
  nvme-multipath: fix hang when disk goes live over reconnect
  nvme: fix RCU hole that allowed for endless looping in multipath round robin
  nvme: allow duplicate NSIDs for private namespaces
  nvmet: remove redundant assignment after left shift
  nvmet: use a private workqueue instead of the system workqueue
  nvme-pci: add quirks for Samsung X5 SSDs
  nvme-pci: expose use_threaded_interrupts read-only in sysfs
  nvme: fix the read-only state for zoned namespaces with unsupposed features
parents b2479de3 a4a6f3c8
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -1867,9 +1867,6 @@ static void nvme_update_disk_info(struct gendisk *disk,
	nvme_config_discard(disk, ns);
	blk_queue_max_write_zeroes_sectors(disk->queue,
					   ns->ctrl->max_zeroes_sectors);

	set_disk_ro(disk, (id->nsattr & NVME_NS_ATTR_RO) ||
		test_bit(NVME_NS_FORCE_RO, &ns->flags));
}

static inline bool nvme_first_scan(struct gendisk *disk)
@@ -1930,6 +1927,8 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
			goto out_unfreeze;
	}

	set_disk_ro(ns->disk, (id->nsattr & NVME_NS_ATTR_RO) ||
		test_bit(NVME_NS_FORCE_RO, &ns->flags));
	set_bit(NVME_NS_READY, &ns->flags);
	blk_mq_unfreeze_queue(ns->disk->queue);

@@ -1942,6 +1941,9 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
	if (nvme_ns_head_multipath(ns->head)) {
		blk_mq_freeze_queue(ns->head->disk->queue);
		nvme_update_disk_info(ns->head->disk, ns, id);
		set_disk_ro(ns->head->disk,
			    (id->nsattr & NVME_NS_ATTR_RO) ||
				    test_bit(NVME_NS_FORCE_RO, &ns->flags));
		nvme_mpath_revalidate_paths(ns);
		blk_stack_limits(&ns->head->disk->queue->limits,
				 &ns->queue->limits, 0);
@@ -3625,15 +3627,20 @@ static const struct attribute_group *nvme_dev_attr_groups[] = {
	NULL,
};

static struct nvme_ns_head *nvme_find_ns_head(struct nvme_subsystem *subsys,
static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
		unsigned nsid)
{
	struct nvme_ns_head *h;

	lockdep_assert_held(&subsys->lock);
	lockdep_assert_held(&ctrl->subsys->lock);

	list_for_each_entry(h, &subsys->nsheads, entry) {
		if (h->ns_id != nsid)
	list_for_each_entry(h, &ctrl->subsys->nsheads, entry) {
		/*
		 * Private namespaces can share NSIDs under some conditions.
		 * In that case we can't use the same ns_head for namespaces
		 * with the same NSID.
		 */
		if (h->ns_id != nsid || !nvme_is_unique_nsid(ctrl, h))
			continue;
		if (!list_empty(&h->list) && nvme_tryget_ns_head(h))
			return h;
@@ -3827,7 +3834,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
	}

	mutex_lock(&ctrl->subsys->lock);
	head = nvme_find_ns_head(ctrl->subsys, nsid);
	head = nvme_find_ns_head(ctrl, nsid);
	if (!head) {
		ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, ids);
		if (ret) {
@@ -4024,6 +4031,16 @@ static void nvme_ns_remove(struct nvme_ns *ns)
	set_capacity(ns->disk, 0);
	nvme_fault_inject_fini(&ns->fault_inject);

	/*
	 * Ensure that !NVME_NS_READY is seen by other threads to prevent
	 * this ns going back into current_path.
	 */
	synchronize_srcu(&ns->head->srcu);

	/* wait for concurrent submissions */
	if (nvme_mpath_clear_current_path(ns))
		synchronize_srcu(&ns->head->srcu);

	mutex_lock(&ns->ctrl->subsys->lock);
	list_del_rcu(&ns->siblings);
	if (list_empty(&ns->head->list)) {
@@ -4035,10 +4052,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
	/* guarantee not available in head->list */
	synchronize_rcu();

	/* wait for concurrent submissions */
	if (nvme_mpath_clear_current_path(ns))
		synchronize_srcu(&ns->head->srcu);

	if (!nvme_ns_head_multipath(ns->head))
		nvme_cdev_del(&ns->cdev, &ns->cdev_device);
	del_gendisk(ns->disk);
@@ -4509,6 +4522,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
	if (ctrl->queue_count > 1) {
		nvme_queue_scan(ctrl);
		nvme_start_queues(ctrl);
		nvme_mpath_update(ctrl);
	}

	nvme_change_uevent(ctrl, "NVME_EVENT=connected");
+27 −5
Original line number Diff line number Diff line
@@ -482,10 +482,11 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)

	/*
	 * Add a multipath node if the subsystems supports multiple controllers.
	 * We also do this for private namespaces as the namespace sharing data could
	 * change after a rescan.
	 * We also do this for private namespaces as the namespace sharing flag
	 * could change after a rescan.
	 */
	if (!(ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) || !multipath)
	if (!(ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) ||
	    !nvme_is_unique_nsid(ctrl, head) || !multipath)
		return 0;

	head->disk = blk_alloc_disk(ctrl->numa_node);
@@ -612,8 +613,17 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc,
	ns->ana_grpid = le32_to_cpu(desc->grpid);
	ns->ana_state = desc->state;
	clear_bit(NVME_NS_ANA_PENDING, &ns->flags);

	if (nvme_state_is_live(ns->ana_state))
	/*
	 * nvme_mpath_set_live() will trigger I/O to the multipath path device
	 * and in turn to this path device.  However we cannot accept this I/O
	 * if the controller is not live.  This may deadlock if called from
	 * nvme_mpath_init_identify() and the ctrl will never complete
	 * initialization, preventing I/O from completing.  For this case we
	 * will reprocess the ANA log page in nvme_mpath_update() once the
	 * controller is ready.
	 */
	if (nvme_state_is_live(ns->ana_state) &&
	    ns->ctrl->state == NVME_CTRL_LIVE)
		nvme_mpath_set_live(ns);
}

@@ -700,6 +710,18 @@ static void nvme_ana_work(struct work_struct *work)
	nvme_read_ana_log(ctrl);
}

void nvme_mpath_update(struct nvme_ctrl *ctrl)
{
	u32 nr_change_groups = 0;

	if (!ctrl->ana_log_buf)
		return;

	mutex_lock(&ctrl->ana_lock);
	nvme_parse_ana_log(ctrl, &nr_change_groups, nvme_update_ana_state);
	mutex_unlock(&ctrl->ana_lock);
}

static void nvme_anatt_timeout(struct timer_list *t)
{
	struct nvme_ctrl *ctrl = from_timer(ctrl, t, anatt_timer);
+23 −0
Original line number Diff line number Diff line
@@ -722,6 +722,25 @@ static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
		return queue_live;
	return __nvme_check_ready(ctrl, rq, queue_live);
}

/*
 * NSID shall be unique for all shared namespaces, or if at least one of the
 * following conditions is met:
 *   1. Namespace Management is supported by the controller
 *   2. ANA is supported by the controller
 *   3. NVM Set are supported by the controller
 *
 * In other case, private namespace are not required to report a unique NSID.
 */
static inline bool nvme_is_unique_nsid(struct nvme_ctrl *ctrl,
		struct nvme_ns_head *head)
{
	return head->shared ||
		(ctrl->oacs & NVME_CTRL_OACS_NS_MNGT_SUPP) ||
		(ctrl->subsys->cmic & NVME_CTRL_CMIC_ANA) ||
		(ctrl->ctratt & NVME_CTRL_CTRATT_NVM_SETS);
}

int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
		void *buf, unsigned bufflen);
int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
@@ -781,6 +800,7 @@ void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
void nvme_mpath_remove_disk(struct nvme_ns_head *head);
int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl);
void nvme_mpath_update(struct nvme_ctrl *ctrl);
void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
void nvme_mpath_stop(struct nvme_ctrl *ctrl);
bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
@@ -852,6 +872,9 @@ static inline int nvme_mpath_init_identify(struct nvme_ctrl *ctrl,
"Please enable CONFIG_NVME_MULTIPATH for full support of multi-port devices.\n");
	return 0;
}
static inline void nvme_mpath_update(struct nvme_ctrl *ctrl)
{
}
static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
{
}
+5 −2
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@
#define NVME_MAX_SEGS	127

static int use_threaded_interrupts;
module_param(use_threaded_interrupts, int, 0);
module_param(use_threaded_interrupts, int, 0444);

static bool use_cmb_sqes = true;
module_param(use_cmb_sqes, bool, 0444);
@@ -3466,7 +3466,10 @@ static const struct pci_device_id nvme_id_table[] = {
				NVME_QUIRK_128_BYTES_SQES |
				NVME_QUIRK_SHARED_TAGS |
				NVME_QUIRK_SKIP_CID_GEN },

	{ PCI_DEVICE(0x144d, 0xa808),   /* Samsung X5 */
		.driver_data =  NVME_QUIRK_DELAY_BEFORE_CHK_RDY|
				NVME_QUIRK_NO_DEEPEST_PS |
				NVME_QUIRK_IGNORE_DEV_SUBNQN, },
	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
	{ 0, }
};
+1 −1
Original line number Diff line number Diff line
@@ -988,7 +988,7 @@ void nvmet_execute_async_event(struct nvmet_req *req)
	ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req;
	mutex_unlock(&ctrl->lock);

	schedule_work(&ctrl->async_event_work);
	queue_work(nvmet_wq, &ctrl->async_event_work);
}

void nvmet_execute_keep_alive(struct nvmet_req *req)
Loading