Commit 9d0e8524 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'nvme-6.9-2024-04-04' of git://git.infradead.org/nvme into block-6.9

Pull NVMe fixes from Keith:

"nvme fixes for Linux 6.9

 - Atomic queue limits fixes (Christoph)
 - Fabrics fixes (Hannes, Daniel)"

* tag 'nvme-6.9-2024-04-04' of git://git.infradead.org/nvme:
  nvme-fc: rename free_ctrl callback to match name pattern
  nvmet-fc: move RCU read lock to nvmet_fc_assoc_exists
  nvmet: implement unique discovery NQN
  nvme: don't create a multipath node for zero capacity devices
  nvme: split nvme_update_zone_info
  nvme-multipath: don't inherit LBA-related fields for the multipath node
parents 22d24a54 205fb5fa
Loading
Loading
Loading
Loading
+32 −9
Original line number Diff line number Diff line
@@ -2076,6 +2076,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
	bool vwc = ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT;
	struct queue_limits lim;
	struct nvme_id_ns_nvm *nvm = NULL;
	struct nvme_zone_info zi = {};
	struct nvme_id_ns *id;
	sector_t capacity;
	unsigned lbaf;
@@ -2088,9 +2089,10 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
	if (id->ncap == 0) {
		/* namespace not allocated or attached */
		info->is_removed = true;
		ret = -ENODEV;
		ret = -ENXIO;
		goto out;
	}
	lbaf = nvme_lbaf_index(id->flbas);

	if (ns->ctrl->ctratt & NVME_CTRL_ATTR_ELBAS) {
		ret = nvme_identify_ns_nvm(ns->ctrl, info->nsid, &nvm);
@@ -2098,8 +2100,14 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
			goto out;
	}

	if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
	    ns->head->ids.csi == NVME_CSI_ZNS) {
		ret = nvme_query_zone_info(ns, lbaf, &zi);
		if (ret < 0)
			goto out;
	}

	blk_mq_freeze_queue(ns->disk->queue);
	lbaf = nvme_lbaf_index(id->flbas);
	ns->head->lba_shift = id->lbaf[lbaf].ds;
	ns->head->nuse = le64_to_cpu(id->nuse);
	capacity = nvme_lba_to_sect(ns->head, le64_to_cpu(id->nsze));
@@ -2112,13 +2120,8 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
		capacity = 0;
	nvme_config_discard(ns, &lim);
	if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
	    ns->head->ids.csi == NVME_CSI_ZNS) {
		ret = nvme_update_zone_info(ns, lbaf, &lim);
		if (ret) {
			blk_mq_unfreeze_queue(ns->disk->queue);
			goto out;
		}
	}
	    ns->head->ids.csi == NVME_CSI_ZNS)
		nvme_update_zone_info(ns, &lim, &zi);
	ret = queue_limits_commit_update(ns->disk->queue, &lim);
	if (ret) {
		blk_mq_unfreeze_queue(ns->disk->queue);
@@ -2201,6 +2204,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
	}

	if (!ret && nvme_ns_head_multipath(ns->head)) {
		struct queue_limits *ns_lim = &ns->disk->queue->limits;
		struct queue_limits lim;

		blk_mq_freeze_queue(ns->head->disk->queue);
@@ -2212,7 +2216,26 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
		set_disk_ro(ns->head->disk, nvme_ns_is_readonly(ns, info));
		nvme_mpath_revalidate_paths(ns);

		/*
		 * queue_limits mixes values that are the hardware limitations
		 * for bio splitting with what is the device configuration.
		 *
		 * For NVMe the device configuration can change after e.g. a
		 * Format command, and we really want to pick up the new format
		 * value here.  But we must still stack the queue limits to the
		 * least common denominator for multipathing to split the bios
		 * properly.
		 *
		 * To work around this, we explicitly set the device
		 * configuration to those that we just queried, but only stack
		 * the splitting limits in to make sure we still obey possibly
		 * lower limitations of other controllers.
		 */
		lim = queue_limits_start_update(ns->head->disk->queue);
		lim.logical_block_size = ns_lim->logical_block_size;
		lim.physical_block_size = ns_lim->physical_block_size;
		lim.io_min = ns_lim->io_min;
		lim.io_opt = ns_lim->io_opt;
		queue_limits_stack_bdev(&lim, ns->disk->part0, 0,
					ns->head->disk->disk_name);
		ret = queue_limits_commit_update(ns->head->disk->queue, &lim);
+2 −2
Original line number Diff line number Diff line
@@ -2428,7 +2428,7 @@ nvme_fc_ctrl_get(struct nvme_fc_ctrl *ctrl)
 * controller. Called after last nvme_put_ctrl() call
 */
static void
nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)
nvme_fc_free_ctrl(struct nvme_ctrl *nctrl)
{
	struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);

@@ -3384,7 +3384,7 @@ static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
	.reg_read32		= nvmf_reg_read32,
	.reg_read64		= nvmf_reg_read64,
	.reg_write32		= nvmf_reg_write32,
	.free_ctrl		= nvme_fc_nvme_ctrl_freed,
	.free_ctrl		= nvme_fc_free_ctrl,
	.submit_async_event	= nvme_fc_submit_async_event,
	.delete_ctrl		= nvme_fc_delete_ctrl,
	.get_address		= nvmf_get_address,
+10 −2
Original line number Diff line number Diff line
@@ -1036,10 +1036,18 @@ static inline bool nvme_disk_is_ns_head(struct gendisk *disk)
}
#endif /* CONFIG_NVME_MULTIPATH */

struct nvme_zone_info {
	u64 zone_size;
	unsigned int max_open_zones;
	unsigned int max_active_zones;
};

int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector,
		unsigned int nr_zones, report_zones_cb cb, void *data);
int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf,
		struct queue_limits *lim);
int nvme_query_zone_info(struct nvme_ns *ns, unsigned lbaf,
		struct nvme_zone_info *zi);
void nvme_update_zone_info(struct nvme_ns *ns, struct queue_limits *lim,
		struct nvme_zone_info *zi);
#ifdef CONFIG_BLK_DEV_ZONED
blk_status_t nvme_setup_zone_mgmt_send(struct nvme_ns *ns, struct request *req,
				       struct nvme_command *cmnd,
+20 −13
Original line number Diff line number Diff line
@@ -35,8 +35,8 @@ static int nvme_set_max_append(struct nvme_ctrl *ctrl)
	return 0;
}

int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf,
		struct queue_limits *lim)
int nvme_query_zone_info(struct nvme_ns *ns, unsigned lbaf,
		struct nvme_zone_info *zi)
{
	struct nvme_effects_log *log = ns->head->effects;
	struct nvme_command c = { };
@@ -89,27 +89,34 @@ int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf,
		goto free_data;
	}

	ns->head->zsze =
		nvme_lba_to_sect(ns->head, le64_to_cpu(id->lbafe[lbaf].zsze));
	if (!is_power_of_2(ns->head->zsze)) {
	zi->zone_size = le64_to_cpu(id->lbafe[lbaf].zsze);
	if (!is_power_of_2(zi->zone_size)) {
		dev_warn(ns->ctrl->device,
			"invalid zone size: %llu for namespace: %u\n",
			ns->head->zsze, ns->head->ns_id);
			zi->zone_size, ns->head->ns_id);
		status = -ENODEV;
		goto free_data;
	}
	zi->max_open_zones = le32_to_cpu(id->mor) + 1;
	zi->max_active_zones = le32_to_cpu(id->mar) + 1;

	blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, ns->queue);
	lim->zoned = 1;
	lim->max_open_zones = le32_to_cpu(id->mor) + 1;
	lim->max_active_zones = le32_to_cpu(id->mar) + 1;
	lim->chunk_sectors = ns->head->zsze;
	lim->max_zone_append_sectors = ns->ctrl->max_zone_append;
free_data:
	kfree(id);
	return status;
}

void nvme_update_zone_info(struct nvme_ns *ns, struct queue_limits *lim,
		struct nvme_zone_info *zi)
{
	lim->zoned = 1;
	lim->max_open_zones = zi->max_open_zones;
	lim->max_active_zones = zi->max_active_zones;
	lim->max_zone_append_sectors = ns->ctrl->max_zone_append;
	lim->chunk_sectors = ns->head->zsze =
		nvme_lba_to_sect(ns->head, zi->zone_size);
	blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, ns->queue);
}

static void *nvme_zns_alloc_report_buffer(struct nvme_ns *ns,
					  unsigned int nr_zones, size_t *buflen)
{
+47 −0
Original line number Diff line number Diff line
@@ -1613,6 +1613,11 @@ static struct config_group *nvmet_subsys_make(struct config_group *group,
		return ERR_PTR(-EINVAL);
	}

	if (sysfs_streq(name, nvmet_disc_subsys->subsysnqn)) {
		pr_err("can't create subsystem using unique discovery NQN\n");
		return ERR_PTR(-EINVAL);
	}

	subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
	if (IS_ERR(subsys))
		return ERR_CAST(subsys);
@@ -2159,7 +2164,49 @@ static const struct config_item_type nvmet_hosts_type = {

static struct config_group nvmet_hosts_group;

static ssize_t nvmet_root_discovery_nqn_show(struct config_item *item,
					     char *page)
{
	return snprintf(page, PAGE_SIZE, "%s\n", nvmet_disc_subsys->subsysnqn);
}

static ssize_t nvmet_root_discovery_nqn_store(struct config_item *item,
		const char *page, size_t count)
{
	struct list_head *entry;
	size_t len;

	len = strcspn(page, "\n");
	if (!len || len > NVMF_NQN_FIELD_LEN - 1)
		return -EINVAL;

	down_write(&nvmet_config_sem);
	list_for_each(entry, &nvmet_subsystems_group.cg_children) {
		struct config_item *item =
			container_of(entry, struct config_item, ci_entry);

		if (!strncmp(config_item_name(item), page, len)) {
			pr_err("duplicate NQN %s\n", config_item_name(item));
			up_write(&nvmet_config_sem);
			return -EINVAL;
		}
	}
	memset(nvmet_disc_subsys->subsysnqn, 0, NVMF_NQN_FIELD_LEN);
	memcpy(nvmet_disc_subsys->subsysnqn, page, len);
	up_write(&nvmet_config_sem);

	return len;
}

CONFIGFS_ATTR(nvmet_root_, discovery_nqn);

static struct configfs_attribute *nvmet_root_attrs[] = {
	&nvmet_root_attr_discovery_nqn,
	NULL,
};

static const struct config_item_type nvmet_root_type = {
	.ct_attrs		= nvmet_root_attrs,
	.ct_owner		= THIS_MODULE,
};

Loading