nvme_fc auto-connect scripts
Subsystems (2)
PATCH 1/1 nvme_fc auto-connect scripts
Sagi recently posted a "one-shot" call to nvme-connect via a systemd script. FC has no problems operating with it assuming all the required connect fields are present (host_traddr required).
However FC is a bit more dynamic, and we've built up scripts that can be triggered whenever a new FC remote port with a discovery subsytem is detected. Whenever such a port is detected (by registration of the remoteport with the nvme_fc transport by the lldd), the transport generates a udev event. A udev rule is created that parses the event information into the FC remote port (traddr) that supports a discovery subsystem and the FC host port that is connected to the FC remote port (host_traddr). The rule then invokes an instance-based systemd service to perform a "nvme connect-all" with the traddr and host-traddr info.
To resolve some issues seen by discovery of remote ports before the udev service was running and where the events were not replayed, there is an additional systemd service that runs once and invokes a script which locates the FC host ports on the system, looks for any connected FC remote ports with discovery subsystems, and invokes a connect-all for them. The FC port information is specific to lpfc attributes currently, but when the shared transport is in place, they will be common.
I don't claim to be a systemd expert, so comments are certainly welcome.
There's a spec file for an rpm, but as a general notice, the installation is as follows:
(as root)
cp 70-nvmefc-autoconnect.conf /usr/lib/dracut/dracut.conf.d/
cp 70-nvmefc-autoconnect.rules /usr/lib/udev/rules.d/
cp nvmefc-connect at .service /usr/lib/systemd/system/
cp nvmefc-boot-connections.service /usr/lib/systemd/system/
cp nvmefc_boot_connections.sh /usr/sbin/lpfc/
chmod 644 /usr/lib/dracut/dracut.conf.d/70-nvmefc-autoconnect.conf chmod 644 /usr/lib/udev/rules.d/70-nvmefc-autoconnect.rules chmod 644 /usr/lib/systemd/system/nvmefc-connect at .service chmod 644 /usr/lib/systemd/system/nvmefc-boot-connections.service chmod 544 /usr/sbin/lpfc/nvmefc_boot_connections.sh
systemctl -q enable nvmefc-boot-connections systemctl -q daemon-reload
udevadm control --reload-rules
udevadm trigger --action=change --subsystem-match=fc dracut -f
The nvmefc_boot_connections.sh script can be put somewhere other than /usr/sbin/lpfc. If moved, the nvmefc-boot-connections.service file must be revised with the proper pathname.
--- nvme-fc-autoconnect/70-nvmefc-autoconnect.conf | 1 + nvme-fc-autoconnect/70-nvmefc-autoconnect.rules | 6 + .../nvmefc-boot-connections.service | 9 ++ nvme-fc-autoconnect/nvmefc-connect.spec | 138 +++++++++++++++++++++ nvme-fc-autoconnect/nvmefc-connect at .service | 14 +++ nvme-fc-autoconnect/nvmefc_boot_connections.sh | 25 ++++ 6 files changed, 193 insertions(+) create mode 100644 nvme-fc-autoconnect/70-nvmefc-autoconnect.conf create mode 100644 nvme-fc-autoconnect/70-nvmefc-autoconnect.rules create mode 100644 nvme-fc-autoconnect/nvmefc-boot-connections.service create mode 100644 nvme-fc-autoconnect/nvmefc-connect.spec create mode 100644 nvme-fc-autoconnect/nvmefc-connect at .service create mode 100644 nvme-fc-autoconnect/nvmefc_boot_connections.sh
nvme-fc-autoconnect/70-nvmefc-autoconnect.conf new file +1 -0
@@ -0,0 +1 @@ +install_items+="/usr/lib/udev/rules.d/70-nvmefc-autoconnect.rules"
nvme-fc-autoconnect/70-nvmefc-autoconnect.rules new file +6 -0
@@ -0,0 +1,6 @@ +# +# nvme_fc: udev event to automatically scan (via discovery controller) +# new FC nvme remote ports and auto-connect to the subsystems they report. +# + +ACTION=="change", SUBSYSTEM=="fc", ENV{FC_EVENT}=="nvmediscovery", ENV{NVMEFC_HOST_TRADDR}=="*", ENV{NVMEFC_TRADDR}=="*", RUN+="/usr/bin/systemctl --no-block start nvmefc-connect at --host-traddr=$env{NVMEFC_HOST_TRADDR}\\x20--traddr=$env{NVMEFC_TRADDR}.service"
nvme-fc-autoconnect/nvmefc-boot-connections.service new file +9 -0
@@ -0,0 +1,9 @@ +[Unit] +Description=Auto-connect to subsystems on FC-NVME devices during boot + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "/usr/sbin/lpfc/nvmefc_boot_connections.sh" + +[Install] +WantedBy=default.target
nvme-fc-autoconnect/nvmefc-connect.spec new file +138 -0
138 lines not on this page · raw message
nvme-fc-autoconnect/nvmefc-connect at .service new file +14 -0
@@ -0,0 +1,14 @@ +# +# Unit file used by 70-nvmefc-autoconnect.rules. +# + +[Unit] +Description=Auto-connect to subsystems on FC-NVME devices +After=syslog.target + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "/usr/sbin/nvme connect-all --transport=fc `/usr/bin/echo -e '%i'`" + +[Install] +WantedBy=default.target
nvme-fc-autoconnect/nvmefc_boot_connections.sh new file +25 -0
@@ -0,0 +1,25 @@ +#!/bin/sh + +connect_discovery_servers_on_host() +{ + INFOFILE=$1/nvme_info + HOSTNM=`basename $1` + if [ -f ${INFOFILE} ] ; then + WWNN=`cat /sys/class/fc_host/${HOSTNM}/node_name` + WWPN=`cat /sys/class/fc_host/${HOSTNM}/port_name` + HOST_TRADDR="nn-${WWNN}:pn-${WWPN}" + cat ${INFOFILE} | awk -v haddr=${HOST_TRADDR} '/^NVME RPORT.*DISCSRVC/{print "/usr/sbin/nvme connect-all --transport=fc --host-traddr=" haddr " --traddr=nn-0" $6 ":pn-0" $4 }' | bash + fi +} + +# need a real check for root permissions here +ROOT=1 + +if [ $ROOT -ne 1 ] ; then + echo "$0: Must be root to execute" + exit 1 +fi + +for f in /sys/class/scsi_host/* ; do + connect_discovery_servers_on_host $f +done
Signature · 1 line
2.13.1
PATCH 1/1 nvme_fc auto-connect scripts
Sorry - this was meant to be posted as an RFC. Please treat it as such.
-- james
PATCH 1/1 nvme_fc auto-connect scripts
In reply to James SmartQuoted 1 line · James Smart
cp
nvmefc_boot_connections.sh/usr/sbin/lpfc/
[...]
Quoted 1 line
+ExecStart=/bin/sh -c "
/usr/sbin/lpfc/nvmefc_boot_connections.sh"
/usr/sbin/lpfc wont get past our package reviewers, %_sbindir (for rpm, I'm sure there is an equivalent for deb as well) should be used there.
Also wouldn't it make sense to have the scripts/services in nvme-cli?
Byte,
Johannes
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
Sagi Grimberg
maintainerPATCH 1/1 nvme_fc auto-connect scripts
Quoted 5 lines
Quoted 2 lines
cp
nvmefc_boot_connections.sh/usr/sbin/lpfc/[...]
Quoted 7 lines
Quoted 1 line
+ExecStart=/bin/sh -c "
/usr/sbin/lpfc/nvmefc_boot_connections.sh"
/usr/sbin/lpfcwont get past our package reviewers, %_sbindir (for rpm, I'm sure there is an equivalent for deb as well) should be used there.Also wouldn't it make sense to have the
scripts/servicesin nvme-cli?
It definitely would.
PATCH 1/1 nvme_fc auto-connect scripts
In reply to James SmartQuoted 22 lines · James Smart
Sagi recently posted a "one-shot" call to nvme-connect via a systemd script. FC has no problems operating with it assuming all the required connect fields are present (
host_traddrrequired).However FC is a bit more dynamic, and we've built up scripts that can be triggered whenever a new FC remote port with a discovery subsytem is detected. Whenever such a port is detected (by registration of the remoteport with the
nvme_fctransport by the lldd), the transport generates a udev event. A udev rule is created that parses the event information into the FC remote port (traddr) that supports a discovery subsystem and the FC host port that is connected to the FC remote port (host_traddr). The rule then invokes an instance-based systemd service to perform a "nvme connect-all" with the traddr and host-traddr info.To resolve some issues seen by discovery of remote ports before the udev service was running and where the events were not replayed, there is an additional systemd service that runs once and invokes a script which locates the FC host ports on the system, looks for any connected FC remote ports with discovery subsystems, and invokes a connect-all for them. The FC port information is specific to lpfc attributes currently, but when the shared transport is in place, they will be common.
Quoted 2 lines
I don't claim to be a systemd expert, so comments are certainly welcome.
In general I'm not in favour of calling 'systemctl start' from a udev rule; this typically will cause systemd to rearrange the internal dependency chain, and might trigger various services to be enabled or disabled.
The 'normal' flow of events is:
kernel device -> uevent -> udev rules -> systemd services
ie for the autoconnect it would be _far_ better if we could have an event per NVMe lport device, as then we could call 'connect' on the lport device.
So a better workflow would be to have the 'discovery' event trigger a 'change' (or 'add'?) event on the lports, and then we could have per-lport udev rules triggering the actualy connect.
Let's see if I can come up with something along these lines.
Cheers,
Hannes
Signature · 5 lines
Dr. Hannes Reinecke Teamlead Storage & Networking hare at suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: F. Imend?rffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG N?rnberg)
PATCH 1/1 nvme_fc auto-connect scripts
Quoted 42 lines · Hannes Reinecke
Quoted 22 lines · James Smart
Sagi recently posted a "one-shot" call to nvme-connect via a systemd script. FC has no problems operating with it assuming all the required connect fields are present (
host_traddrrequired).However FC is a bit more dynamic, and we've built up scripts that can be triggered whenever a new FC remote port with a discovery subsytem is detected. Whenever such a port is detected (by registration of the remoteport with the
nvme_fctransport by the lldd), the transport generates a udev event. A udev rule is created that parses the event information into the FC remote port (traddr) that supports a discovery subsystem and the FC host port that is connected to the FC remote port (host_traddr). The rule then invokes an instance-based systemd service to perform a "nvme connect-all" with the traddr and host-traddr info.To resolve some issues seen by discovery of remote ports before the udev service was running and where the events were not replayed, there is an additional systemd service that runs once and invokes a script which locates the FC host ports on the system, looks for any connected FC remote ports with discovery subsystems, and invokes a connect-all for them. The FC port information is specific to lpfc attributes currently, but when the shared transport is in place, they will be common.
Quoted 2 lines
I don't claim to be a systemd expert, so comments are certainly welcome.
In general I'm not in favour of calling 'systemctl start' from a udev rule; this typically will cause systemd to rearrange the internal dependency chain, and might trigger various services to be enabled or disabled.
The 'normal' flow of events is:
kernel device -> uevent -> udev rules -> systemd services
ie for the autoconnect it would be _far_ better if we could have an event per NVMe lport device, as then we could call 'connect' on the lport device.
So a better workflow would be to have the 'discovery' event trigger a 'change' (or 'add'?) event on the lports, and then we could have per-lport udev rules triggering the actualy connect.
Quoted 5 lines
Let's see if I can come up with something along these lines.
Cheers,
Hannes
I'm certainly open to better options. udev/systemd is far from nice.? However, what I did has quite a bit of precedence.
I have no idea what you would scan on by just an lport. It's not enough for nvme-cli. You must have the lport and the rport information, which is passed via the udev event info and which must also be passed to nvme connect-all
-- james
PATCH 1/1 nvme_fc auto-connect scripts
Quoted 49 lines · James Smart
Quoted 42 lines · Hannes Reinecke
Quoted 22 lines · James Smart
Sagi recently posted a "one-shot" call to nvme-connect via a systemd script. FC has no problems operating with it assuming all the required connect fields are present (
host_traddrrequired).However FC is a bit more dynamic, and we've built up scripts that can be triggered whenever a new FC remote port with a discovery subsytem is detected. Whenever such a port is detected (by registration of the remoteport with the
nvme_fctransport by the lldd), the transport generates a udev event.? A udev rule is created that parses the event information into the FC remote port (traddr) that supports a discovery subsystem and the FC host port that is connected to the FC remote port (host_traddr). The rule then invokes an instance-based systemd service to perform a "nvme connect-all" with the traddr and host-traddr info.To resolve some issues seen by discovery of remote ports before the udev service was running and where the events were not replayed, there is an additional systemd service that runs once and invokes a script which locates the FC host ports on the system, looks for any connected FC remote ports with discovery subsystems, and invokes a connect-all for them.? The FC port information is specific to lpfc attributes currently, but when the shared transport is in place, they will be common.
Quoted 2 lines
I don't claim to be a systemd expert, so comments are certainly welcome.
In general I'm not in favour of calling 'systemctl start' from a udev rule; this typically will cause systemd to rearrange the internal dependency chain, and might trigger various services to be enabled or disabled.
The 'normal' flow of events is:
kernel device -> uevent -> udev rules -> systemd services
ie for the autoconnect it would be _far_ better if we could have an event per NVMe lport device, as then we could call 'connect' on the lport device.
So a better workflow would be to have the 'discovery' event trigger a 'change' (or 'add'?) event on the lports, and then we could have per-lport udev rules triggering the actualy connect.
Quoted 5 lines
Let's see if I can come up with something along these lines.
Cheers,
Hannes
Quoted 8 lines
I'm certainly open to better options. udev/systemd is far from nice.? However, what I did has quite a bit of precedence.
I have no idea what you would scan on by just an lport. It's not enough for nvme-cli. You must have the lport and the rport information, which is passed via the udev event info and which must also be passed to nvme connect-all
Oh, I know that.
What I would prefer is to have a single udev rule per nvme connection, containing both lport and rport information.
That would relieve us of having additional configuration, and we can enable/disable connection by just having that udev rule. This works pretty well; we're doing it exactly the same way on S/390 for the network and zfcp connections.
So if we have that then we only need to know when the lport/rport combination is ready; once that is done we can call the udev rule. Ideally we'll be getting an event containing both of these informations, then udev will be selecting the correct rule automatically.
Cheers,
Hannes
Signature · 5 lines
Dr. Hannes Reinecke Teamlead Storage & Networking hare at suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: F. Imend?rffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG N?rnberg)
PATCH 1/1 nvme_fc auto-connect scripts
Quoted 13 lines · Hannes Reinecke
Oh, I know that.
What I would prefer is to have a single udev rule per nvme connection, containing both lport and rport information.
That would relieve us of having additional configuration, and we can enable/disable connection by just having that udev rule. This works pretty well; we're doing it exactly the same way on S/390 for the network and zfcp connections.
So if we have that then we only need to know when the lport/rport combination is ready; once that is done we can call the udev rule. Ideally we'll be getting an event containing both of these informations, then udev will be selecting the correct rule automatically.
Quoted 3 lines
Cheers,
Hannes
The main reason for the systemd use was the potential duration of the resulting nvme connect-all. The scripts are simple if udev makes the nvme cli call and don't require anything other than a single generic rule. But given its potential stalls, very bad.
If I understand you correctly, what you describe requires apriori knowledge of the connections in order to add the udevs rule. This is a step backward from current FC behavior and what users are used to.
-- james
PATCH 1/1 nvme_fc auto-connect scripts
Quoted 18 lines · James Smart
Quoted 13 lines · Hannes Reinecke
Oh, I know that.
What I would prefer is to have a single udev rule per nvme connection, containing both lport and rport information.
That would relieve us of having additional configuration, and we can enable/disable connection by just having that udev rule. This works pretty well; we're doing it exactly the same way on S/390 for the network and zfcp connections.
So if we have that then we only need to know when the lport/rport combination is ready; once that is done we can call the udev rule. Ideally we'll be getting an event containing both of these informations, then udev will be selecting the correct rule automatically.Quoted 3 lines
Cheers,
Hannes
Quoted 9 lines
The main reason for the systemd use was the potential duration of the resulting nvme connect-all. The scripts are simple if udev makes the nvme cli call and don't require anything other than a single generic rule. But given its potential stalls, very bad.
If I understand you correctly, what you describe requires apriori knowledge of the connections in order to add the udevs rule. This is a step backward from current FC behavior and what users are used to.
So, here's my take for this:
# cat 65-nvme-fc-connect-nvmf-test-subsys1.rules
SUBSYSTEM!="block, GOTO="nvme_autoconnect_end"
ACTION!="add|change", GOTO="nvme_autoconnect_end"
ENV{FC_EVENT}!="nvmediscovery", GOTO="nvme_autoconnect_end"
ENV{NVMEFC_HOST_TRADDR}!="?*", GOTO="nvme_autoconnect_end"
ENV{NVMEFC_TRADDR}!="?*", GOTO="nvme_autoconnect_end"
RUN+="/usr/sbin/nvme connect -t fc \
--host-traddr=$env{NVMEFC_HOST_TRADDR} \
-n nvmf-test-subsys1 -a $env{NVMEFC_TRADDR}"
LABEL="nvme_autoconnect_end"Obviously, we would need to filter for the appropriate values of traddr and host_traddr to not attempt connections to non-existing namespaces.
However, I do see the problem of nvme connect stalls; if we were having a systemd service we would solve this issue nicely, indeed. But then we shouldn't activate the service, it should rather be activated per default, but depend on a specifice NVMe-FC _target_, which should be presented by the discovery event.
Let's see what I can cobble together here.
Cheers,
Hannes
Signature · 5 lines
Dr. Hannes Reinecke Teamlead Storage & Networking hare at suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: F. Imend?rffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG N?rnberg)
PATCH 1/1 nvme_fc auto-connect scripts
Quoted 1 line · Hannes Reinecke
On 10/28/2017 06:08 PM, James Smart wrote:
[ .. ]
Quoted 26 lines
Quoted 10 lines
The main reason for the systemd use was the potential duration of the resulting nvme connect-all. The scripts are simple if udev makes the nvme cli call and don't require anything other than a single generic rule. But given its potential stalls, very bad.
If I understand you correctly, what you describe requires apriori knowledge of the connections in order to add the udevs rule. This is a step backward from current FC behavior and what users are used to.
So, here's my take for this:
# cat 65-nvme-fc-connect-nvmf-test-subsys1.rules SUBSYSTEM!="block, GOTO="nvme_autoconnect_end" ACTION!="add|change", GOTO="nvme_autoconnect_end" ENV{FC_EVENT}!="nvmediscovery", GOTO="nvme_autoconnect_end" ENV{NVMEFC_HOST_TRADDR}!="?*", GOTO="nvme_autoconnect_end" ENV{NVMEFC_TRADDR}!="?*", GOTO="nvme_autoconnect_end" RUN+="/usr/sbin/nvme connect -t fc \ --host-traddr=$env{NVMEFC_HOST_TRADDR} \ -n nvmf-test-subsys1 -a $env{NVMEFC_TRADDR}" LABEL="nvme_autoconnect_end"Obviously, we would need to filter for the appropriate values of traddr and
host_traddrto not attempt connections to non-existing namespaces.
Quoted 8 lines
However, I do see the problem of nvme connect stalls; if we were having a systemd service we would solve this issue nicely, indeed. But then we shouldn't activate the service, it should rather be activated per default, but depend on a specifice NVMe-FC _target_, which should be presented by the discovery event.
Let's see what I can cobble together here.
Upon further review, we actually _could_ avoid delays upon the 'nvme connect' call if we were delegating the call to the connect workqueue:
drivers/nvme/host/fc.c +0 -0
@@ -3302,28 +3302,7 @@ nvme_fc_init_ctrl(struct device *dev, struct
nvmf_ctrl_options *opts,
nvme_fc_set_ctrl_devloss(ctrl, opts);
- ret = nvme_fc_create_association(ctrl);
- if (ret) {
- ctrl->ctrl.opts = NULL; - /* initiate nvme ctrl ref counting teardown */ - nvme_uninit_ctrl(&ctrl->ctrl);
-
- /* Remove core ctrl ref. */
- nvme_put_ctrl(&ctrl->ctrl);
-
- /* as we're past the point where we transition to the ref
- * counting teardown path, if we return a bad pointer here, - * the calling routine, thinking it's prior to the - * transition, will do an rport put. Since the teardown - * path also does a rport put, we do an extra get here to - * so proper order/teardown happens. - */
- nvme_fc_rport_get(rport);
-
- if (ret > 0)
- ret = -EIO;
- return ERR_PTR(ret);
- }
+ queue_delayed_work(nvme_fc_wq, &ctrl->connect_work, 0);
Then it should be perfectly possible to have a udev rule with just kicking off the 'nvme connect', any eventual cleanup would be done by either the number of reconnects being exhausted or dev_loss_tmo kicking in. James?
Cheers,
Hannes
Signature · 5 lines
Dr. Hannes Reinecke Teamlead Storage & Networking hare at suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: F. Imend?rffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG N?rnberg)