linux-nvme.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: mwilck@suse.com
To: Sagi Grimberg <sagi@grimberg.me>, Hannes Reinecke <hare@suse.de>,
	Keith Busch <kbusch@kernel.org>
Cc: Chaitanya Kulkarni <Chaitanya.Kulkarni@wdc.com>,
	linux-nvme@lists.infradead.org,
	Enzo Matsumiya <ematsumiya@suse.de>,
	Martin Wilck <mwilck@suse.com>
Subject: [PATCH v2 13/16] monitor: add "query device" message exchange
Date: Sat,  6 Mar 2021 01:36:56 +0100	[thread overview]
Message-ID: <20210306003659.21207-14-mwilck@suse.com> (raw)
In-Reply-To: <20210306003659.21207-1-mwilck@suse.com>

From: Martin Wilck <mwilck@suse.com>

This message exchange sends a message with the current connection
parameters to the parent monitor process and attempts to obtain
the instance number of an existing discovery controller for the
given connection.

For making this work, another callback is added to monitor_callbacks()
do be called before attempting a discovery connection.
---
 fabrics.c |   4 ++
 monitor.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 monitor.h |   2 +
 3 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/fabrics.c b/fabrics.c
index a9e28d8..64468db 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -1376,6 +1376,10 @@ int do_discover(char *argstr, bool connect, enum nvme_print_flags flags,
 		free(fabrics_cfg.device);
 		fabrics_cfg.device = NULL;
 	}
+
+	if (!fabrics_cfg.device && monitor && monitor->query_dev)
+		monitor->query_dev(argstr, &fabrics_cfg.device);
+
 	if (!fabrics_cfg.device)
 		fabrics_cfg.device = find_ctrl_with_connectargs(cargs);
 	free_connect_args(cargs);
diff --git a/monitor.c b/monitor.c
index 7f08772..f2d9512 100644
--- a/monitor.c
+++ b/monitor.c
@@ -236,6 +236,19 @@ static ssize_t monitor_child_message(char *buf, size_t size, size_t len)
  *      This exchange is initiated in notify_new_discovery(), which is passed
  *      as "notify" callback for do_discover().
  *    - parent responds with MON_MSG_ACK (or MON_MSG_ERR if an error occurs).
+ *
+ * "Query existing device" exchange:
+ *   - The child sends a MON_MSG_QDEV message to the parent after determining
+ *      transport connection parameters, but before attempting to create a
+ *      discovery controller.
+ *      Payload: the transport parameter string to be sent to /dev/nvme-fabrics.
+ *      This exchange is initiated in query_device(), which is passed as
+ *      "query_dev" callback for discover_from_conf_file().
+ *    - The parent responds:
+ *       * MON_MSG_SDEV ("send device") if an existing controller device was found
+ *         Payload: the instance number of the controller ("0" for /dev/nvme0").
+ *       * MON_MSG_ACK: if no existing controller device was found.
+ *       * MON_MSG_ERR: in case of an error.
  */
 
 static const char monitor_magic[] = "NVMM";
@@ -243,6 +256,8 @@ enum {
 	MON_MSG_ACK = 0,
 	MON_MSG_ERR,
 	MON_MSG_NEW,
+	MON_MSG_QDEV,
+	MON_MSG_SDEV,
 	__MAX_MON_MSG__,
 };
 
@@ -256,6 +271,8 @@ static const char *const monitor_opcode[] = {
 	[MON_MSG_ACK] = "ACK ",
 	[MON_MSG_ERR] = "ERR ",
 	[MON_MSG_NEW] = "NEW ",
+	[MON_MSG_QDEV] = "QDEV",
+	[MON_MSG_SDEV] = "SDEV",
 };
 
 static int monitor_msg_hdr(char *buf, size_t len, int opcode)
@@ -321,6 +338,11 @@ static int monitor_check_resp(const char *buf, size_t len, int req_opcode)
 		if (resp_opcode == MON_MSG_ACK && len == 0)
 			rc = 0;
 		break;
+	case MON_MSG_QDEV:
+		if ((resp_opcode == MON_MSG_ACK && len == 0) ||
+		    (resp_opcode == MON_MSG_SDEV && len > 0))
+			rc = 0;
+		break;
 	default:
 		break;
 	}
@@ -358,10 +380,54 @@ static void notify_new_discovery(const char *argstr, int instance)
 	monitor_check_resp(buf, rc, MON_MSG_NEW);
 }
 
+static void query_device(const char *argstr, char **device)
+{
+	char buf[MSG_SIZE];
+	size_t len = 0;
+	ssize_t rc;
+	int instance;
+	char dummy;
+	char *pbuf, *dev;
+
+	if ((rc = monitor_msg_hdr(buf, sizeof(buf), MON_MSG_QDEV)) < 0) {
+		msg(LOG_ERR, "failed to create msghdr: %s\n", strerror(-rc));
+		return;
+	}
+	len += rc;
+	if ((rc = safe_snprintf(buf + len, sizeof(buf) - len, "%s", argstr)) < 0) {
+		msg(LOG_ERR, "failed to create msg: %s\n", strerror(-rc));
+		return;
+	}
+	len += rc;
+	if ((rc = monitor_child_message(buf, sizeof(buf), len)) < 0)
+		return;
+
+	len = rc;
+	pbuf = buf;
+	if ((rc = monitor_check_resp(pbuf, len, MON_MSG_QDEV)) < 0)
+		return;
+
+	pbuf += rc;
+	len -= rc;
+	if (len == 0) {
+		msg(LOG_INFO, "monitor didn't report existing device\n");
+		return;
+	} else if (sscanf(pbuf, "%d%c", &instance, &dummy) != 1) {
+		msg(LOG_WARNING, "got bad device info: %s\n", pbuf);
+		return;
+	}
+
+	if (asprintf(&dev, "nvme%d", instance) < 0)
+		return;
+
+	msg(LOG_INFO, "monitor reported existing device %s\n", dev);
+	*device = dev;
+}
+
 static const struct monitor_callbacks discover_callbacks = {
 	.notify = notify_new_discovery,
+	.query_dev = query_device,
 };
-
 struct comm_event {
 	struct event e;
 	struct sockaddr_un addr;
@@ -399,6 +465,41 @@ static int handle_child_msg_new(char *buf, size_t size, ssize_t *len, ssize_t of
 	return MON_MSG_ACK;
 }
 
+static int handle_child_msg_qdev(char *buf, size_t size, ssize_t *len, ssize_t ofs)
+{
+	ssize_t rc = MON_MSG_ERR;
+	struct nvme_connection *co;
+	char *pbuf = buf;
+
+	if (*len <= ofs) {
+		msg(LOG_ERR, "short packet (len=%zd)\n", *len);
+		return MON_MSG_ERR;
+	}
+
+	pbuf += ofs;
+	rc = conndb_add_disc_ctrl(pbuf, &co);
+	if (rc != 0 && rc != -EEXIST) {
+		msg(LOG_WARNING, "invalid address: \"%s\"\n", buf);
+		return MON_MSG_ERR;
+	}
+
+	if (co->discovery_instance != -1) {
+		rc = monitor_msg_hdr(buf, size, MON_MSG_SDEV);
+		if (rc >= 0) {
+			buf += rc;
+			if ((rc = snprintf(buf, size - rc, "%d",
+					   co->discovery_instance)) >= 0) {
+				*len = ofs + rc;
+				return MON_MSG_SDEV;
+			}
+		}
+		msg(LOG_ERR, "failed to create SDEV message: %s\n",
+		    strerror(-rc));
+	}
+
+	return MON_MSG_ACK;
+}
+
 static int handle_child_msg(struct comm_event *comm, ssize_t len)
 {
 	ssize_t rc, ofs;
@@ -418,8 +519,14 @@ static int handle_child_msg(struct comm_event *comm, ssize_t len)
 						  sizeof(comm->message),
 						  &len, ofs);
 			break;
+		case MON_MSG_QDEV:
+			rc = handle_child_msg_qdev(comm->message,
+						   sizeof(comm->message),
+						   &len, ofs);
+			break;
 		case MON_MSG_ACK:
 		case MON_MSG_ERR:
+		case MON_MSG_SDEV:
 			msg(LOG_ERR, "unexpected message: %s\n", monitor_opcode[opcode]);
 			rc = MON_MSG_ERR;
 			break;
diff --git a/monitor.h b/monitor.h
index 01ae4de..3c2f6da 100644
--- a/monitor.h
+++ b/monitor.h
@@ -2,9 +2,11 @@
 #define _MONITOR_H
 
 typedef void (*disc_notify_cb)(const char *argstr, int instance);
+typedef void (*disc_query_dev_cb)(const char *argstr, char **device);
 
 struct monitor_callbacks {
 	disc_notify_cb notify;
+	disc_query_dev_cb query_dev;
 };
 
 extern int aen_monitor(const char *desc, int argc, char **argv);
-- 
2.29.2


_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

  parent reply	other threads:[~2021-03-06  0:55 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-06  0:36 [PATCH v2 00/16] nvme-cli: add "nvme monitor" subcommand mwilck
2021-03-06  0:36 ` [PATCH v2 01/16] fabrics: export symbols required for monitor functionality mwilck
2021-03-06  0:36 ` [PATCH v2 02/16] nvme-cli: add code for event and timeout handling mwilck
2021-03-17  0:32   ` Martin Wilck
2021-03-19 16:42     ` Martin Wilck
2021-03-30 22:06       ` Martin Wilck
2021-03-06  0:36 ` [PATCH v2 03/16] monitor: add basic "nvme monitor" functionality mwilck
2021-03-06  0:36 ` [PATCH v2 04/16] monitor: implement uevent handling mwilck
2021-03-06  0:36 ` [PATCH v2 05/16] conn-db: add simple connection registry mwilck
2021-03-06  0:36 ` [PATCH v2 06/16] monitor: monitor_discovery(): try to reuse existing controllers mwilck
2021-03-06  0:36 ` [PATCH v2 07/16] monitor: kill running discovery tasks on exit mwilck
2021-03-06  0:36 ` [PATCH v2 08/16] monitor: add option --cleanup / -C mwilck
2021-03-06  0:36 ` [PATCH v2 09/16] monitor: handling of add/remove uevents for nvme controllers mwilck
2021-03-06  0:36 ` [PATCH v2 10/16] monitor: discover from conf file on startup mwilck
2021-03-06  0:36 ` [PATCH v2 11/16] monitor: watch discovery.conf with inotify mwilck
2021-03-06  0:36 ` [PATCH v2 12/16] monitor: add parent/child messaging and "notify" message exchange mwilck
2021-03-06  0:36 ` mwilck [this message]
2021-03-06  0:36 ` [PATCH v2 14/16] completions: add completions for nvme monitor mwilck
2021-03-06  0:36 ` [PATCH v2 15/16] nvmf-autoconnect: add unit file for nvme-monitor.service mwilck
2021-03-06  0:36 ` [PATCH v2 16/16] nvme-monitor(1): add man page for nvme-monitor mwilck

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=20210306003659.21207-14-mwilck@suse.com \
    --to=mwilck@suse.com \
    --cc=Chaitanya.Kulkarni@wdc.com \
    --cc=ematsumiya@suse.de \
    --cc=hare@suse.de \
    --cc=kbusch@kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --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;
as well as URLs for NNTP newsgroup(s).