git: 17c907dd7acf - main - ctladm: Add nvterminate command to drop active NVMeoF associations

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Fri, 03 May 2024 00:16:13 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=17c907dd7acf15cb54d6eca53fcc9eb7401f95ba

commit 17c907dd7acf15cb54d6eca53fcc9eb7401f95ba
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-05-02 23:35:20 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-05-02 23:38:39 +0000

    ctladm: Add nvterminate command to drop active NVMeoF associations
    
    Reviewed by:    imp
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D44729
---
 usr.sbin/ctladm/ctladm.8 | 13 +++++++++
 usr.sbin/ctladm/ctladm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index 6e084c30de36..2c90e12ef924 100644
--- a/usr.sbin/ctladm/ctladm.8
+++ b/usr.sbin/ctladm/ctladm.8
@@ -202,6 +202,9 @@
 .Op Fl v
 .Op Fl x
 .Nm
+.Ic nvterminate
+.Aq Fl a | Fl c Ar controller-id | Fl h Ar name
+.Nm
 .Ic help
 .Sh DESCRIPTION
 The
@@ -876,6 +879,16 @@ Dump the raw XML.
 The sessions list information from the kernel comes in XML format, and this
 option allows the display of the raw XML data.
 .El
+.It Ic nvterminate
+Forcibly terminate NVMeoF associations matching criteria.
+.Bl -tag -width 11n
+.It Fl a
+Terminate all associations.
+.It Fl c
+Specify controller ID.
+.It Fl h
+Specify host name.
+.El
 .It Ic help
 Display
 .Nm
diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c
index d0456986fd12..0b034b21b2b1 100644
--- a/usr.sbin/ctladm/ctladm.c
+++ b/usr.sbin/ctladm/ctladm.c
@@ -115,7 +115,8 @@ typedef enum {
 	CTLADM_CMD_ISLOGOUT,
 	CTLADM_CMD_ISTERMINATE,
 	CTLADM_CMD_LUNMAP,
-	CTLADM_CMD_NVLIST
+	CTLADM_CMD_NVLIST,
+	CTLADM_CMD_NVTERMINATE
 } ctladm_cmdfunction;
 
 typedef enum {
@@ -182,6 +183,7 @@ static struct ctladm_opts option_table[] = {
 	{"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"},
 	{"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:o:s:"},
 	{"nvlist", CTLADM_CMD_NVLIST, CTLADM_ARG_NONE, "vx"},
+	{"nvterminate", CTLADM_CMD_NVTERMINATE, CTLADM_ARG_NONE, "ac:h:"},
 	{"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:O:d:crp:qt:w:W:x"},
 	{"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ilp:qvx"},
 	{"prin", CTLADM_CMD_PRES_IN, CTLADM_ARG_NEED_TL, "a:"},
@@ -4066,6 +4068,70 @@ bailout:
 	return (retval);
 }
 
+static int
+cctl_nvterminate(int fd, int argc, char **argv, char *combinedopt)
+{
+	struct ctl_nvmf req;
+	int retval = 0, c;
+	int all = 0, cntlid = -1, nargs = 0;
+	char *hostnqn = NULL;
+
+	while ((c = getopt(argc, argv, combinedopt)) != -1) {
+		switch (c) {
+		case 'a':
+			all = 1;
+			nargs++;
+			break;
+		case 'c':
+			cntlid = strtoul(optarg, NULL, 0);
+			nargs++;
+			break;
+		case 'h':
+			hostnqn = strdup(optarg);
+			if (hostnqn == NULL)
+				err(1, "%s: strdup", __func__);
+			nargs++;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (nargs == 0)
+		errx(1, "%s: either -a, -c, or -h must be specified",
+		    __func__);
+	if (nargs > 1)
+		errx(1, "%s: only one of -a, -c, or -h may be specified",
+		    __func__);
+
+	bzero(&req, sizeof(req));
+	req.type = CTL_NVMF_TERMINATE;
+	req.data.terminate.cntlid = cntlid;
+	if (hostnqn != NULL)
+		strlcpy(req.data.terminate.hostnqn,
+		    hostnqn, sizeof(req.data.terminate.hostnqn));
+	if (all != 0)
+		req.data.terminate.all = 1;
+
+	if (ioctl(fd, CTL_NVMF, &req) == -1) {
+		warn("%s: error issuing CTL_NVMF ioctl", __func__);
+		retval = 1;
+		goto bailout;
+	}
+
+	if (req.status != CTL_NVMF_OK) {
+		warnx("%s: error returned from CTL NVMeoF connection "
+		    "termination request:\n%s", __func__, req.error_str);
+		retval = 1;
+		goto bailout;
+	}
+
+	printf("NVMeoF connections terminated\n");
+
+bailout:
+	return (retval);
+}
+
 void
 usage(int error)
 {
@@ -4113,11 +4179,12 @@ usage(int error)
 "         ctladm islogout    <-a | -c connection-id | -i name | -p portal>\n"
 "         ctladm isterminate <-a | -c connection-id | -i name | -p portal>\n"
 "         ctladm nvlist      [-v | -x]\n"
+"         ctladm nvterminate <-a | -c controller-id | -h name>\n"
 "         ctladm dumpooa\n"
 "         ctladm dumpstructs\n"
 "         ctladm help\n"
 "General Options:\n"
-"-I intiator_id           : defaults to 7, used to change the initiator id\n"
+"-I initiator_id          : defaults to 7, used to change the initiator id\n"
 "-C retries               : specify the number of times to retry this command\n"
 "-D devicename            : specify the device to operate on\n"
 "                         : (default is %s)\n"
@@ -4512,6 +4579,9 @@ main(int argc, char **argv)
 	case CTLADM_CMD_NVLIST:
 	        retval = cctl_nvlist(fd, argc, argv, combinedopt);
 		break;
+	case CTLADM_CMD_NVTERMINATE:
+	        retval = cctl_nvterminate(fd, argc, argv, combinedopt);
+		break;
 	case CTLADM_CMD_HELP:
 	default:
 		usage(retval);