public inbox for linux-nvme@lists.infradead.org
 help / color / mirror / Atom feed
From: Nilay Shroff <nilay@linux.ibm.com>
To: dwagner@suse.de
Cc: linux-nvme@lists.infradead.org, kbusch@kernel.org, hch@lst.de,
	sagi@grimberg.me, gjoyce@ibm.com, msmurthy@imap.linux.ibm.com,
	axboe@fb.com, Nilay Shroff <nilay@linux.ibm.com>
Subject: [PATCH nvme-cli] nvme: warn about attaching a namespace to unknown controller
Date: Thu, 20 Jun 2024 18:25:45 +0530	[thread overview]
Message-ID: <20240620125604.3017138-1-nilay@linux.ibm.com> (raw)

Sometime it's possible for a multi-controller NVMe disk to have only
one of its controller discovered by the kernel. And if this happens
then it's also possible for a user to create and then attach a namespace
to a controller which has not been discovered by the kernel. In such a
case the attached namespace can't be used for IO because there's no path
to reach such namespace from the kernel.

This patch helps to warn about such case to user when user attempts to
attach a namepsace to an undiscovered controller by kernel. If this warning
appears to the user then user have about 10 seconds of time to abort the
operation by pressing CTRL-C. If user doesn't abort this operation
within 10 seconds of timeout then nvme cli goes ahead as usual and attach
the namespace to the controller.

Link: https://lore.kernel.org/all/f1a7c1e2-3203-4b7a-a922-82fa812455bd@linux.ibm.com/
Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
---
 nvme.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 86 insertions(+), 4 deletions(-)

diff --git a/nvme.c b/nvme.c
index ba760901..0f3b3297 100644
--- a/nvme.c
+++ b/nvme.c
@@ -2811,6 +2811,84 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *
 	return err;
 }
 
+static bool nvme_match_subsys_device_filter(nvme_subsystem_t s, nvme_ctrl_t c,
+		   nvme_ns_t ns, void *f_arg)
+{
+	nvme_ctrl_t _c;
+	const char *devname = (const char *)f_arg;
+
+	if (!s)
+		return true;
+
+	nvme_subsystem_for_each_ctrl(s, _c) {
+		if (!strcmp(devname, nvme_ctrl_get_name(_c)))
+			return true;
+	}
+
+	return false;
+}
+
+static int nvme_cli_ns_validate_cntlid(__u32 nsid, struct nvme_dev *dev,
+				       int *list, int num)
+{
+	const char *cntlid;
+	int __cntlid;
+	char *p;
+	nvme_host_t h;
+	nvme_subsystem_t s;
+	nvme_ctrl_t c;
+	nvme_root_t r = NULL;
+	int i, err, matched = 0;
+	nvme_scan_filter_t filter = nvme_match_subsys_device_filter;
+
+	r = nvme_create_root(stderr, log_level);
+	if (!r) {
+		nvme_show_error("Failed to create topology root: %s",
+				nvme_strerror(errno));
+		return -errno;
+	}
+
+	err = nvme_scan_topology(r, filter, (void *)dev->name);
+	if (err < 0) {
+		if (errno != ENOENT)
+			nvme_show_error("Failed to scan topology: %s",
+					nvme_strerror(errno));
+		nvme_free_tree(r);
+		return err;
+	}
+	nvme_for_each_host(r, h) {
+		nvme_for_each_subsystem(h, s) {
+			nvme_subsystem_for_each_ctrl(s, c) {
+				cntlid = nvme_ctrl_get_cntlid(c);
+				errno = 0;
+				__cntlid = strtoul(cntlid, &p, 0);
+				if (errno || *p != 0)
+					continue;
+				for (i = 0; i < num; i++) {
+					if (__cntlid == list[i])
+						matched++;
+				}
+			}
+		}
+	}
+
+	nvme_free_tree(r);
+
+	if (matched != num) {
+		fprintf(stderr,
+			"You are about to attach namespace 0x%x to an undiscovered nvme controller.\n",
+			nsid);
+		fprintf(stderr,
+			"WARNING: Attaching nampespace to undiscovered nvme controller may have undesired side effect!\n"
+			"You may not be able to perform any IO to such namespace.\n"
+			"You have 10 seconds to press Ctrl-C to cancel this operation.\n\n");
+		sleep(10);
+		fprintf(stderr, "Sending attach-ns operation ...\n");
+	}
+
+	return 0;
+}
+
 static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd)
 {
 	_cleanup_free_ struct nvme_ctrl_list *cntlist = NULL;
@@ -2866,12 +2944,16 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s
 
 	nvme_init_ctrl_list(cntlist, num, ctrlist);
 
-	if (attach)
-		err = nvme_cli_ns_attach_ctrls(dev, cfg.namespace_id,
-					       cntlist);
-	else
+	if (attach) {
+		err = nvme_cli_ns_validate_cntlid(cfg.namespace_id, dev,
+						  list, num);
+		if (!err)
+			err = nvme_cli_ns_attach_ctrls(dev, cfg.namespace_id,
+						       cntlist);
+	} else {
 		err = nvme_cli_ns_detach_ctrls(dev, cfg.namespace_id,
 					       cntlist);
+	}
 
 	if (!err)
 		printf("%s: Success, nsid:%d\n", cmd->name, cfg.namespace_id);
-- 
2.45.1



             reply	other threads:[~2024-06-20 12:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-20 12:55 Nilay Shroff [this message]
2024-06-21 15:08 ` [PATCH nvme-cli] nvme: warn about attaching a namespace to unknown controller Keith Busch
2024-06-22 10:35   ` Nilay Shroff
2024-06-24 19:32     ` Keith Busch
2024-06-25  6:23       ` Nilay Shroff

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240620125604.3017138-1-nilay@linux.ibm.com \
    --to=nilay@linux.ibm.com \
    --cc=axboe@fb.com \
    --cc=dwagner@suse.de \
    --cc=gjoyce@ibm.com \
    --cc=hch@lst.de \
    --cc=kbusch@kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=msmurthy@imap.linux.ibm.com \
    --cc=sagi@grimberg.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox