[PATCH 2/3] nvme: move hidden device and multipath handling out of nvme_update_ns_info

Christoph Hellwig hch at lst.de
Wed Aug 28 23:31:29 PDT 2024


Turn nvme_update_ns_info into a pure multiplexer and move the real work
into nvme_update_ns_info_generic and nvme_update_ns_block, which allows
to set the flags more coherently while the queue is still frozen.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/core.c | 55 ++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 30 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 51cb3b001b3757..81d2a09dd00f30 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2147,12 +2147,18 @@ static int nvme_update_ns_info_generic(struct nvme_ns *ns,
 	lim = queue_limits_start_update(ns->disk->queue);
 	nvme_set_ctrl_limits(ns->ctrl, &lim);
 	ret = queue_limits_commit_update(ns->disk->queue, &lim);
-	set_disk_ro(ns->disk, nvme_ns_is_readonly(ns, info));
-	blk_mq_unfreeze_queue(ns->disk->queue);
+	if (ret)
+		goto out_unfreeze;
 
 	/* Hide the block-interface for these devices */
-	if (!ret)
-		ret = -ENODEV;
+	ns->disk->flags |= GENHD_FL_HIDDEN;
+	set_bit(NVME_NS_READY, &ns->flags);
+	set_disk_ro(ns->disk, nvme_ns_is_readonly(ns, info));
+
+out_unfreeze:
+	blk_mq_unfreeze_queue(ns->disk->queue);
+	if (nvme_ns_head_multipath(ns->head) && !ret)
+		ret = nvme_update_ns_info_mpath(ns, info, true);
 	return ret;
 }
 
@@ -2163,6 +2169,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
 	struct nvme_id_ns_nvm *nvm = NULL;
 	struct nvme_zone_info zi = {};
 	struct nvme_id_ns *id;
+	bool unsupported = false;
 	sector_t capacity;
 	unsigned lbaf;
 	int ret;
@@ -2188,6 +2195,11 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
 	if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
 	    ns->head->ids.csi == NVME_CSI_ZNS) {
 		ret = nvme_query_zone_info(ns, lbaf, &zi);
+		if (ret == -ENODEV) {
+			unsupported = true;
+			ns->disk->flags |= GENHD_FL_HIDDEN;
+			goto done;
+		}
 		if (ret < 0)
 			goto out;
 	}
@@ -2238,6 +2250,8 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
 	 */
 	if ((id->dlfeat & 0x7) == 0x1 && (id->dlfeat & (1 << 3)))
 		ns->head->features |= NVME_NS_DEAC;
+
+done:
 	set_disk_ro(ns->disk, nvme_ns_is_readonly(ns, info));
 	set_bit(NVME_NS_READY, &ns->flags);
 	blk_mq_unfreeze_queue(ns->disk->queue);
@@ -2252,50 +2266,31 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
 out:
 	kfree(nvm);
 	kfree(id);
+
+	if (nvme_ns_head_multipath(ns->head) && !ret)
+		ret = nvme_update_ns_info_mpath(ns, info, unsupported);
 	return ret;
 }
 
 static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
 {
-	bool unsupported = false;
-	int ret;
-
 	switch (info->ids.csi) {
 	case NVME_CSI_ZNS:
 		if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
 			dev_info(ns->ctrl->device,
 	"block device for nsid %u not supported without CONFIG_BLK_DEV_ZONED\n",
 				info->nsid);
-			ret = nvme_update_ns_info_generic(ns, info);
-			break;
+			return nvme_update_ns_info_generic(ns, info);
 		}
-		ret = nvme_update_ns_info_block(ns, info);
-		break;
+		return nvme_update_ns_info_block(ns, info);
 	case NVME_CSI_NVM:
-		ret = nvme_update_ns_info_block(ns, info);
-		break;
+		return nvme_update_ns_info_block(ns, info);
 	default:
 		dev_info(ns->ctrl->device,
 			"block device for nsid %u not supported (csi %u)\n",
 			info->nsid, info->ids.csi);
-		ret = nvme_update_ns_info_generic(ns, info);
-		break;
+		return nvme_update_ns_info_generic(ns, info);
 	}
-
-	/*
-	 * If probing fails due an unsupported feature, hide the block device,
-	 * but still allow other access.
-	 */
-	if (ret == -ENODEV) {
-		ns->disk->flags |= GENHD_FL_HIDDEN;
-		set_bit(NVME_NS_READY, &ns->flags);
-		unsupported = true;
-		ret = 0;
-	}
-
-	if (nvme_ns_head_multipath(ns->head) && !ret)
-		ret = nvme_update_ns_info_mpath(ns, info, unsupported);
-	return ret;
 }
 
 int nvme_ns_get_unique_id(struct nvme_ns *ns, u8 id[16],
-- 
2.43.0




More information about the Linux-nvme mailing list