* [PATCH v2 0/15] IB SRP initiator patches for kernel 3.11
@ 2013-06-28 12:45 Bart Van Assche
[not found] ` <51CD856A.3010102-HInyCGIudOg@public.gmane.org>
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Bart Van Assche @ 2013-06-28 12:45 UTC (permalink / raw)
To: Roland Dreier, David Dillow, Vu Pham, Sebastian Riemer,
linux-rdma, linux-scsi
The purpose of this InfiniBand SRP initiator patch series is as follows:
- Make the SRP initiator driver better suited for use in a H.A. setup.
Speed up failover by reducing the IB RC retry count and by notifying
multipathd faster about transport layer failures by adding
fast_io_fail_tmo and dev_loss_tmo parameters.
- Make the SRP initiator better suited for use on NUMA systems by
making the HCA completion vector configurable.
Changes since the v1 of the "IB SRP initiator patches for kernel 3.11"
patch series:
- scsi_transport_srp: Allowed both fast_io_fail and dev_loss timeouts
to be disabled.
- scsi_transport_srp, srp_reconnect_rport(): switched from
scsi_block_requests() to scsi_target_block() for blocking SCSI command
processing temporarily.
- scsi_transport_srp, srp_start_tl_fail_timers(): only block SCSI device
command processing if the fast_io_fail timer is enabled.
- Changed srp_abort() such that upon transport offline the value
FAST_IO_FAIL is returned instead of SUCCESS.
- Fixed a race condition in the "maintain single connection" patch: a
new login after removal had started but before removal had finished
still could create a duplicate connection. Fixed this by deferring
removal from the target list until removal has finished.
- Modified the error message in the same patch for reporting that a
duplicate connection has been rejected.
- Modified patch 2/15 such that all possible race conditions with
srp_claim_req() are addressed.
- Documented the comp_vector and tl_retry_count login string parameters.
- Updated dev_loss_tmo and fast_io_fail_tmo documentation - mentioned
"off" is a valid choice.
Changes compared to v5 of the "Make ib_srp better suited for H.A.
purposes" patch series:
- Left out patches that are already upstream.
- Made it possible to set dev_loss_tmo to "off". This is useful in a
setup using initiator side mirroring to avoid that new /dev/sd* names
are reassigned after a failover or cable pull and reinsert.
- Added kernel module parameters to ib_srp for configuring default
values of the fast_io_fail_tmo and dev_loss_tmo parameters.
- Added a patch from Dotan Barak that fixes a kernel oops during rmmod
triggered by resource allocation failure at module load time.
- Avoid duplicate connections by refusing relogins instead of dropping
duplicate connections, as proposed by Sebastian Riemer.
- Added a patch from Sebastian Riemer for failing SCSI commands
silently.
- Added a patch from Vu Pham to make the transport layer (IB RC) retry
count configurable.
- Made HCA completion vector configurable.
Changes since v4:
- Added a patch for removing SCSI devices upon a port down event
Changes since v3:
- Restored the dev_loss_tmo and fast_io_fail_tmo sysfs attributes.
- Included a patch to fix an ib_srp crash that could be triggered by
cable pulling.
Changes since v2:
- Addressed the v2 review comments.
- Dropped the patches that have already been merged.
- Dropped the patches for integration with multipathd.
- Dropped the micro-optimization of the IB completion handlers.
The individual patches in this series are as follows:
0001-IB-srp-Fix-remove_one-crash-due-to-resource-exhausti.patch
0002-IB-srp-Fix-race-between-srp_queuecommand-and-srp_cla.patch
0003-IB-srp-Avoid-that-srp_reset_host-is-skipped-after-a-.patch
0004-IB-srp-Fail-I-O-fast-if-target-offline.patch
0005-IB-srp-Skip-host-settle-delay.patch
0006-IB-srp-Maintain-a-single-connection-per-I_T-nexus.patch
0007-IB-srp-Keep-rport-as-long-as-the-IB-transport-layer.patch
0008-scsi_transport_srp-Add-transport-layer-error-handlin.patch
0009-IB-srp-Add-srp_terminate_io.patch
0010-IB-srp-Use-SRP-transport-layer-error-recovery.patch
0011-IB-srp-Start-timers-if-a-transport-layer-error-occur.patch
0012-IB-srp-Fail-SCSI-commands-silently.patch
0013-IB-srp-Make-HCA-completion-vector-configurable.patch
0014-IB-srp-Make-transport-layer-retry-count-configurable.patch
0015-IB-srp-Bump-driver-version-and-release-date.patch
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 06/15] IB/srp: Maintain a single connection per I_T nexus
[not found] ` <51CD856A.3010102-HInyCGIudOg@public.gmane.org>
@ 2013-06-28 12:51 ` Bart Van Assche
[not found] ` <51CD86CE.8080804-HInyCGIudOg@public.gmane.org>
2013-06-28 12:52 ` [PATCH v2 07/15] IB/srp: Keep rport as long as the IB transport layer Bart Van Assche
1 sibling, 1 reply; 11+ messages in thread
From: Bart Van Assche @ 2013-06-28 12:51 UTC (permalink / raw)
To: Roland Dreier
Cc: David Dillow, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi
An SRP target is required to maintain a single connection between
initiator and target. This means that if the 'add_target' attribute
is used to create a second connection to a target that the first
connection will be logged out and that the SCSI error handler will
kick in. The SCSI error handler will cause the SRP initiator to
reconnect, which will cause I/O over the second connection to fail.
Avoid such ping-pong behavior by disabling relogins. Note: if
reconnecting manually is necessary, that is possible by deleting
and recreating an rport via sysfs.
Signed-off-by: Bart Van Assche <bvanassche-HInyCGIudOg@public.gmane.org>
Signed-off-by: Sebastian Riemer <sebastian.riemer-EIkl63zCoXaH+58JC4qpiA@public.gmane.org>
Cc: Roland Dreier <roland-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: David Dillow <dillowda-1Heg1YXhbW8@public.gmane.org>
Cc: Vu Pham <vu-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
drivers/infiniband/ulp/srp/ib_srp.c | 44 +++++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 01212c9..4eba1f7 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -542,11 +542,11 @@ static void srp_remove_work(struct work_struct *work)
WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
+ srp_remove_target(target);
+
spin_lock(&target->srp_host->target_lock);
list_del(&target->list);
spin_unlock(&target->srp_host->target_lock);
-
- srp_remove_target(target);
}
static void srp_rport_delete(struct srp_rport *rport)
@@ -2010,6 +2010,36 @@ static struct class srp_class = {
.dev_release = srp_release_dev
};
+/**
+ * srp_conn_unique() - check whether the connection to a target is unique
+ */
+static bool srp_conn_unique(struct srp_host *host,
+ struct srp_target_port *target)
+{
+ struct srp_target_port *t;
+ bool ret = false;
+
+ if (target->state == SRP_TARGET_REMOVED)
+ goto out;
+
+ ret = true;
+
+ spin_lock(&host->target_lock);
+ list_for_each_entry(t, &host->target_list, list) {
+ if (t != target &&
+ target->id_ext == t->id_ext &&
+ target->ioc_guid == t->ioc_guid &&
+ target->initiator_ext == t->initiator_ext) {
+ ret = false;
+ break;
+ }
+ }
+ spin_unlock(&host->target_lock);
+
+out:
+ return ret;
+}
+
/*
* Target ports are added by writing
*
@@ -2266,6 +2296,16 @@ static ssize_t srp_create_target(struct device *dev,
if (ret)
goto err;
+ if (!srp_conn_unique(target->srp_host, target)) {
+ shost_printk(KERN_INFO, target->scsi_host,
+ PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
+ be64_to_cpu(target->id_ext),
+ be64_to_cpu(target->ioc_guid),
+ be64_to_cpu(target->initiator_ext));
+ ret = -EEXIST;
+ goto err;
+ }
+
if (!host->srp_dev->fmr_pool && !target->allow_ext_sg &&
target->cmd_sg_cnt < target->sg_tablesize) {
pr_warn("No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 07/15] IB/srp: Keep rport as long as the IB transport layer
[not found] ` <51CD856A.3010102-HInyCGIudOg@public.gmane.org>
2013-06-28 12:51 ` [PATCH v2 06/15] IB/srp: Maintain a single connection per I_T nexus Bart Van Assche
@ 2013-06-28 12:52 ` Bart Van Assche
2013-06-30 21:06 ` David Dillow
1 sibling, 1 reply; 11+ messages in thread
From: Bart Van Assche @ 2013-06-28 12:52 UTC (permalink / raw)
To: Roland Dreier
Cc: David Dillow, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi,
James Bottomley
Keep the rport data structure around after srp_remove_host() has
finished until cleanup of the IB transport layer has finished
completely. This is necessary because later patches use the rport
pointer inside the queuecommand callback. Without this patch
accessing the rport from inside a queuecommand callback is racy
because srp_remove_host() must be invoked before scsi_remove_host()
and because the queuecommand callback may get invoked after
srp_remove_host() has finished.
Signed-off-by: Bart Van Assche <bvanassche-HInyCGIudOg@public.gmane.org>
Cc: Roland Dreier <roland-BHEL68pLQRGGvPXPguhicg@public.gmane.org>
Cc: James Bottomley <JBottomley-MU7nAjRaF3makBO8gow8eQ@public.gmane.org>
Cc: David Dillow <dillowda-1Heg1YXhbW8@public.gmane.org>
Cc: Vu Pham <vu-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Cc: Sebastian Riemer <sebastian.riemer-EIkl63zCoXaH+58JC4qpiA@public.gmane.org>
---
drivers/infiniband/ulp/srp/ib_srp.c | 3 +++
drivers/infiniband/ulp/srp/ib_srp.h | 1 +
drivers/scsi/scsi_transport_srp.c | 18 ++++++++++++++++++
include/scsi/scsi_transport_srp.h | 2 ++
4 files changed, 24 insertions(+)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 4eba1f7..cb86be5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -526,11 +526,13 @@ static void srp_remove_target(struct srp_target_port *target)
WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
srp_del_scsi_host_attr(target->scsi_host);
+ srp_rport_get(target->rport);
srp_remove_host(target->scsi_host);
scsi_remove_host(target->scsi_host);
srp_disconnect_target(target);
ib_destroy_cm_id(target->cm_id);
srp_free_target_ib(target);
+ srp_rport_put(target->rport);
srp_free_req_data(target);
scsi_host_put(target->scsi_host);
}
@@ -1984,6 +1986,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
}
rport->lld_data = target;
+ target->rport = rport;
spin_lock(&host->target_lock);
list_add_tail(&target->list, &host->target_list);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 66fbedd..1817ed5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -153,6 +153,7 @@ struct srp_target_port {
u16 io_class;
struct srp_host *srp_host;
struct Scsi_Host *scsi_host;
+ struct srp_rport *rport;
char target_name[32];
unsigned int scsi_id;
unsigned int sg_tablesize;
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index f379c7f..f7ba94a 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -185,6 +185,24 @@ static int srp_host_match(struct attribute_container *cont, struct device *dev)
}
/**
+ * srp_rport_get() - increment rport reference count
+ */
+void srp_rport_get(struct srp_rport *rport)
+{
+ get_device(&rport->dev);
+}
+EXPORT_SYMBOL(srp_rport_get);
+
+/**
+ * srp_rport_put() - decrement rport reference count
+ */
+void srp_rport_put(struct srp_rport *rport)
+{
+ put_device(&rport->dev);
+}
+EXPORT_SYMBOL(srp_rport_put);
+
+/**
* srp_rport_add - add a SRP remote port to the device hierarchy
* @shost: scsi host the remote port is connected to.
* @ids: The port id for the remote port.
diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h
index ff0f04a..5a2d2d1 100644
--- a/include/scsi/scsi_transport_srp.h
+++ b/include/scsi/scsi_transport_srp.h
@@ -38,6 +38,8 @@ extern struct scsi_transport_template *
srp_attach_transport(struct srp_function_template *);
extern void srp_release_transport(struct scsi_transport_template *);
+extern void srp_rport_get(struct srp_rport *rport);
+extern void srp_rport_put(struct srp_rport *rport);
extern struct srp_rport *srp_rport_add(struct Scsi_Host *,
struct srp_rport_identifiers *);
extern void srp_rport_del(struct srp_rport *);
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling
2013-06-28 12:45 [PATCH v2 0/15] IB SRP initiator patches for kernel 3.11 Bart Van Assche
[not found] ` <51CD856A.3010102-HInyCGIudOg@public.gmane.org>
@ 2013-06-28 12:53 ` Bart Van Assche
2013-06-30 21:05 ` David Dillow
2013-06-28 12:56 ` [PATCH v2 12/15] IB/srp: Fail SCSI commands silently Bart Van Assche
2 siblings, 1 reply; 11+ messages in thread
From: Bart Van Assche @ 2013-06-28 12:53 UTC (permalink / raw)
To: Roland Dreier
Cc: David Dillow, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi,
James Bottomley
Add the necessary functions in the SRP transport module to allow
an SRP initiator driver to implement transport layer error handling
similar to the functionality already provided by the FC transport
layer. This includes:
- Support for implementing fast_io_fail_tmo, the time that should
elapse after having detected a transport layer problem and
before failing I/O.
- Support for implementing dev_loss_tmo, the time that should
elapse after having detected a transport layer problem and
before removing a remote port.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Roland Dreier <roland@purestorage.com>
Cc: James Bottomley <JBottomley@Parallels.com>
Cc: David Dillow <dillowda@ornl.gov>
Cc: Vu Pham <vu@mellanox.com>
Cc: Sebastian Riemer <sebastian.riemer@profitbricks.com>
---
Documentation/ABI/stable/sysfs-transport-srp | 37 ++
drivers/scsi/scsi_transport_srp.c | 477 +++++++++++++++++++++++++-
include/scsi/scsi_transport_srp.h | 62 +++-
3 files changed, 573 insertions(+), 3 deletions(-)
diff --git a/Documentation/ABI/stable/sysfs-transport-srp b/Documentation/ABI/stable/sysfs-transport-srp
index b36fb0d..6a4d651 100644
--- a/Documentation/ABI/stable/sysfs-transport-srp
+++ b/Documentation/ABI/stable/sysfs-transport-srp
@@ -5,6 +5,24 @@ Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
Description: Instructs an SRP initiator to disconnect from a target and to
remove all LUNs imported from that target.
+What: /sys/class/srp_remote_ports/port-<h>:<n>/dev_loss_tmo
+Date: October 1, 2013
+KernelVersion: 3.11
+Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
+Description: Number of seconds the SCSI layer will wait after a transport
+ layer error has been observed before removing a target port.
+ Zero means immediate removal. Setting this attribute to "off"
+ will disable this behavior.
+
+What: /sys/class/srp_remote_ports/port-<h>:<n>/fast_io_fail_tmo
+Date: October 1, 2013
+KernelVersion: 3.11
+Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
+Description: Number of seconds the SCSI layer will wait after a transport
+ layer error has been observed before failing I/O. Zero means
+ immediate removal. Setting this attribute to "off" will
+ disable this behavior.
+
What: /sys/class/srp_remote_ports/port-<h>:<n>/port_id
Date: June 27, 2007
KernelVersion: 2.6.24
@@ -12,8 +30,27 @@ Contact: linux-scsi@vger.kernel.org
Description: 16-byte local SRP port identifier in hexadecimal format. An
example: 4c:49:4e:55:58:20:56:49:4f:00:00:00:00:00:00:00.
+What: /sys/class/srp_remote_ports/port-<h>:<n>/reconnect_delay
+Date: October 1, 2013
+KernelVersion: 3.11
+Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
+Description: Number of seconds the SCSI layer will wait after a reconnect
+ attempt failed before retrying.
+
What: /sys/class/srp_remote_ports/port-<h>:<n>/roles
Date: June 27, 2007
KernelVersion: 2.6.24
Contact: linux-scsi@vger.kernel.org
Description: Role of the remote port. Either "SRP Initiator" or "SRP Target".
+
+What: /sys/class/srp_remote_ports/port-<h>:<n>/state
+Date: October 1, 2013
+KernelVersion: 3.11
+Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
+Description: State of the transport layer to the remote port. "running" if
+ the transport layer is operational; "blocked" if a transport
+ layer error has been encountered but the fail_io_fast_tmo
+ timer has not yet fired; "fail-fast" after the
+ fail_io_fast_tmo timer has fired and before the "dev_loss_tmo"
+ timer has fired; "lost" after the "dev_loss_tmo" timer has
+ fired and before the port is finally removed.
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index f7ba94a..44b27dd 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -24,11 +24,13 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/delay.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport_srp.h>
#include "scsi_transport_srp_internal.h"
@@ -38,7 +40,7 @@ struct srp_host_attrs {
#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data)
#define SRP_HOST_ATTRS 0
-#define SRP_RPORT_ATTRS 3
+#define SRP_RPORT_ATTRS 8
struct srp_internal {
struct scsi_transport_template t;
@@ -54,6 +56,25 @@ struct srp_internal {
#define dev_to_rport(d) container_of(d, struct srp_rport, dev)
#define transport_class_to_srp_rport(dev) dev_to_rport((dev)->parent)
+static inline struct Scsi_Host *rport_to_shost(struct srp_rport *r)
+{
+ return dev_to_shost(r->dev.parent);
+}
+
+/**
+ * srp_tmo_valid() - check timeout combination validity
+ *
+ * If both a fast I/O fail and a device loss timeout have been configured then
+ * the fast I/O fail timeout must be below the device loss timeout.
+ */
+int srp_tmo_valid(int fast_io_fail_tmo, int dev_loss_tmo)
+{
+ return (fast_io_fail_tmo < 0 || dev_loss_tmo < 0 ||
+ fast_io_fail_tmo < dev_loss_tmo) &&
+ fast_io_fail_tmo < LONG_MAX / HZ &&
+ dev_loss_tmo < LONG_MAX / HZ ? 0 : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(srp_tmo_valid);
static int srp_host_setup(struct transport_container *tc, struct device *dev,
struct device *cdev)
@@ -134,10 +155,433 @@ static ssize_t store_srp_rport_delete(struct device *dev,
static DEVICE_ATTR(delete, S_IWUSR, NULL, store_srp_rport_delete);
+static ssize_t show_srp_rport_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ static const char *const state_name[] = {
+ [SRP_RPORT_RUNNING] = "running",
+ [SRP_RPORT_BLOCKED] = "blocked",
+ [SRP_RPORT_FAIL_FAST] = "fail-fast",
+ [SRP_RPORT_LOST] = "lost",
+ };
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ enum srp_rport_state state = rport->state;
+
+ return sprintf(buf, "%s\n",
+ (unsigned)state < ARRAY_SIZE(state_name) ?
+ state_name[state] : "???");
+}
+
+static DEVICE_ATTR(state, S_IRUGO, show_srp_rport_state, NULL);
+
+static ssize_t show_reconnect_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+
+ return sprintf(buf, "%d\n", rport->reconnect_delay);
+}
+
+static ssize_t store_reconnect_delay(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, const size_t count)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ char ch[16];
+ int res, delay;
+
+ sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
+ res = kstrtoint(ch, 0, &delay);
+ if (res)
+ goto out;
+
+ res = mutex_lock_interruptible(&rport->mutex);
+ if (res)
+ goto out;
+ if (rport->reconnect_delay <= 0 && delay > 0 &&
+ rport->state != SRP_RPORT_RUNNING) {
+ queue_delayed_work(system_long_wq, &rport->reconnect_work,
+ delay * HZ);
+ } else if (delay <= 0) {
+ cancel_delayed_work(&rport->reconnect_work);
+ }
+ rport->reconnect_delay = delay;
+ mutex_unlock(&rport->mutex);
+
+ res = count;
+
+out:
+ return res;
+}
+
+static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR, show_reconnect_delay,
+ store_reconnect_delay);
+
+static ssize_t show_failed_reconnects(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+
+ return sprintf(buf, "%d\n", rport->failed_reconnects);
+}
+
+static DEVICE_ATTR(failed_reconnects, S_IRUGO, show_failed_reconnects, NULL);
+
+static ssize_t show_srp_rport_fast_io_fail_tmo(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+
+ if (rport->fast_io_fail_tmo >= 0)
+ return sprintf(buf, "%d\n", rport->fast_io_fail_tmo);
+ else
+ return sprintf(buf, "off\n");
+}
+
+static ssize_t store_srp_rport_fast_io_fail_tmo(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ char ch[16], *p;
+ int res;
+ int fast_io_fail_tmo;
+
+ sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
+ p = strchr(ch, '\n');
+ if (p)
+ *p = '\0';
+
+ if (strcmp(ch, "off") != 0) {
+ res = kstrtoint(ch, 0, &fast_io_fail_tmo);
+ if (res)
+ goto out;
+ } else {
+ fast_io_fail_tmo = -1;
+ }
+ res = srp_tmo_valid(fast_io_fail_tmo, rport->dev_loss_tmo);
+ if (res)
+ goto out;
+ rport->fast_io_fail_tmo = fast_io_fail_tmo;
+ res = count;
+
+out:
+ return res;
+}
+
+static DEVICE_ATTR(fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+ show_srp_rport_fast_io_fail_tmo,
+ store_srp_rport_fast_io_fail_tmo);
+
+static ssize_t show_srp_rport_dev_loss_tmo(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+
+ if (rport->dev_loss_tmo >= 0)
+ return sprintf(buf, "%d\n", rport->dev_loss_tmo);
+ else
+ return sprintf(buf, "off\n");
+}
+
+static ssize_t store_srp_rport_dev_loss_tmo(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ char ch[16];
+ int res;
+ int dev_loss_tmo;
+
+ sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
+ if (strcmp(ch, "off") != 0) {
+ res = kstrtoint(ch, 0, &dev_loss_tmo);
+ if (res)
+ goto out;
+ } else {
+ dev_loss_tmo = -1;
+ }
+ res = srp_tmo_valid(rport->fast_io_fail_tmo, dev_loss_tmo);
+ if (res)
+ goto out;
+ rport->dev_loss_tmo = dev_loss_tmo;
+ res = count;
+
+out:
+ return res;
+}
+
+static DEVICE_ATTR(dev_loss_tmo, S_IRUGO | S_IWUSR,
+ show_srp_rport_dev_loss_tmo,
+ store_srp_rport_dev_loss_tmo);
+
+static int srp_rport_set_state(struct srp_rport *rport,
+ enum srp_rport_state new_state)
+{
+ enum srp_rport_state old_state = rport->state;
+
+ lockdep_assert_held(&rport->mutex);
+
+ switch (new_state) {
+ case SRP_RPORT_RUNNING:
+ switch (old_state) {
+ case SRP_RPORT_LOST:
+ goto invalid;
+ default:
+ break;
+ }
+ break;
+ case SRP_RPORT_BLOCKED:
+ switch (old_state) {
+ case SRP_RPORT_RUNNING:
+ break;
+ default:
+ goto invalid;
+ }
+ break;
+ case SRP_RPORT_FAIL_FAST:
+ switch (old_state) {
+ case SRP_RPORT_LOST:
+ goto invalid;
+ default:
+ break;
+ }
+ break;
+ case SRP_RPORT_LOST:
+ break;
+ }
+ rport->state = new_state;
+ return 0;
+
+invalid:
+ return -EINVAL;
+}
+
+/**
+ * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
+ */
+static int scsi_request_fn_active(struct Scsi_Host *shost)
+{
+ struct scsi_device *sdev;
+ struct request_queue *q;
+ int request_fn_active = 0;
+
+ shost_for_each_device(sdev, shost) {
+ q = sdev->request_queue;
+
+ spin_lock_irq(q->queue_lock);
+ request_fn_active += q->request_fn_active;
+ spin_unlock_irq(q->queue_lock);
+ }
+
+ return request_fn_active;
+}
+
+/**
+ * srp_reconnect_rport() - reconnect to an SRP target port
+ *
+ * Blocks SCSI command queueing before invoking reconnect() such that
+ * queuecommand() won't be invoked concurrently with reconnect(). This is
+ * important since a reconnect() implementation may reallocate resources
+ * needed by queuecommand(). Please note that this function neither waits
+ * until outstanding requests have finished nor tries to abort these. It is
+ * the responsibility of the reconnect() function to finish outstanding
+ * commands before reconnecting to the target port.
+ */
+int srp_reconnect_rport(struct srp_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct srp_internal *i = to_srp_internal(shost->transportt);
+ struct scsi_device *sdev;
+ int res;
+
+ pr_debug("SCSI host %s\n", dev_name(&shost->shost_gendev));
+
+ res = mutex_lock_interruptible(&rport->mutex);
+ if (res)
+ goto out;
+ scsi_target_block(&shost->shost_gendev);
+ while (scsi_request_fn_active(shost))
+ msleep(20);
+ res = i->f->reconnect(rport);
+ pr_debug("%s (state %d): transport.reconnect() returned %d\n",
+ dev_name(&shost->shost_gendev), rport->state, res);
+ if (res == 0) {
+ cancel_delayed_work(&rport->fast_io_fail_work);
+ cancel_delayed_work(&rport->dev_loss_work);
+ rport->failed_reconnects = 0;
+ srp_rport_set_state(rport, SRP_RPORT_RUNNING);
+ scsi_target_unblock(&shost->shost_gendev, SDEV_RUNNING);
+ /*
+ * It can occur that after fast_io_fail_tmo expired and before
+ * dev_loss_tmo expired that the SCSI error handler has
+ * offlined one or more devices. scsi_target_unblock() doesn't
+ * change the state of these devices into running, so do that
+ * explicitly.
+ */
+ spin_lock_irq(shost->host_lock);
+ __shost_for_each_device(sdev, shost)
+ if (sdev->sdev_state == SDEV_OFFLINE)
+ sdev->sdev_state = SDEV_RUNNING;
+ spin_unlock_irq(shost->host_lock);
+ } else if (rport->state == SRP_RPORT_RUNNING) {
+ srp_rport_set_state(rport, SRP_RPORT_FAIL_FAST);
+ scsi_target_unblock(&shost->shost_gendev,
+ SDEV_TRANSPORT_OFFLINE);
+ }
+ mutex_unlock(&rport->mutex);
+
+out:
+ return res;
+}
+EXPORT_SYMBOL(srp_reconnect_rport);
+
+/**
+ * srp_reconnect_work() - reconnect and schedule a new attempt if necessary
+ */
+static void srp_reconnect_work(struct work_struct *work)
+{
+ struct srp_rport *rport = container_of(to_delayed_work(work),
+ struct srp_rport, reconnect_work);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ int delay, res;
+
+ res = srp_reconnect_rport(rport);
+ if (res != 0) {
+ shost_printk(KERN_ERR, shost,
+ "reconnect attempt %d failed (%d)\n",
+ ++rport->failed_reconnects, res);
+ delay = rport->reconnect_delay *
+ min(100, max(1, rport->failed_reconnects - 10));
+ if (delay > 0)
+ queue_delayed_work(system_long_wq,
+ &rport->reconnect_work, delay * HZ);
+ }
+}
+
+static void __rport_fast_io_fail_timedout(struct srp_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct srp_internal *i;
+
+ lockdep_assert_held(&rport->mutex);
+
+ if (srp_rport_set_state(rport, SRP_RPORT_FAIL_FAST))
+ return;
+ scsi_target_unblock(rport->dev.parent, SDEV_TRANSPORT_OFFLINE);
+
+ /* Involve the LLD if possible to terminate all I/O on the rport. */
+ i = to_srp_internal(shost->transportt);
+ if (i->f->terminate_rport_io)
+ i->f->terminate_rport_io(rport);
+}
+
+/**
+ * rport_fast_io_fail_timedout() - fast I/O failure timeout handler
+ *
+ * Unblocks the SCSI host.
+ */
+static void rport_fast_io_fail_timedout(struct work_struct *work)
+{
+ struct srp_rport *rport = container_of(to_delayed_work(work),
+ struct srp_rport, fast_io_fail_work);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+
+ pr_debug("fast_io_fail_tmo expired for %s.\n",
+ dev_name(&shost->shost_gendev));
+
+ mutex_lock(&rport->mutex);
+ __rport_fast_io_fail_timedout(rport);
+ mutex_unlock(&rport->mutex);
+}
+
+/**
+ * rport_dev_loss_timedout() - device loss timeout handler
+ */
+static void rport_dev_loss_timedout(struct work_struct *work)
+{
+ struct srp_rport *rport = container_of(to_delayed_work(work),
+ struct srp_rport, dev_loss_work);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct srp_internal *i = to_srp_internal(shost->transportt);
+
+ pr_err("dev_loss_tmo expired for %s.\n",
+ dev_name(&shost->shost_gendev));
+
+ mutex_lock(&rport->mutex);
+ WARN_ON(srp_rport_set_state(rport, SRP_RPORT_LOST) != 0);
+ scsi_target_unblock(rport->dev.parent, SDEV_TRANSPORT_OFFLINE);
+ mutex_unlock(&rport->mutex);
+
+ i->f->rport_delete(rport);
+}
+
+/**
+ * srp_start_tl_fail_timers() - start the transport layer failure timers
+ *
+ * Start the transport layer fast I/O failure and device loss timers. Do not
+ * modify a timer that was already started.
+ */
+void srp_start_tl_fail_timers(struct srp_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ int fast_io_fail_tmo, dev_loss_tmo, delay;
+
+ mutex_lock(&rport->mutex);
+ delay = rport->reconnect_delay;
+ fast_io_fail_tmo = rport->fast_io_fail_tmo;
+ dev_loss_tmo = rport->dev_loss_tmo;
+ pr_debug("%s current state: %d\n", dev_name(&shost->shost_gendev),
+ rport->state);
+
+ if (fast_io_fail_tmo >= 0 &&
+ srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) {
+ pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev),
+ rport->state);
+ scsi_target_block(&shost->shost_gendev);
+ queue_delayed_work(system_long_wq, &rport->fast_io_fail_work,
+ 1UL * fast_io_fail_tmo * HZ);
+ }
+ if (dev_loss_tmo >= 0)
+ queue_delayed_work(system_long_wq, &rport->dev_loss_work,
+ 1UL * dev_loss_tmo * HZ);
+ if (delay > 0)
+ queue_delayed_work(system_long_wq, &rport->reconnect_work,
+ 1UL * delay * HZ);
+ mutex_unlock(&rport->mutex);
+}
+EXPORT_SYMBOL(srp_start_tl_fail_timers);
+
+/**
+ * srp_timed_out() - SRP transport intercept of the SCSI timeout EH
+ *
+ * If a timeout occurs while an rport is in the blocked state, ask the SCSI
+ * EH to continue waiting (BLK_EH_RESET_TIMER). Otherwise let the SCSI core
+ * handle the timeout (BLK_EH_NOT_HANDLED).
+ *
+ * Note: This function is called from soft-IRQ context and with the request
+ * queue lock held.
+ */
+static enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd)
+{
+ struct scsi_device *sdev = scmd->device;
+
+ pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev));
+ return scsi_device_blocked(sdev) ? BLK_EH_RESET_TIMER :
+ BLK_EH_NOT_HANDLED;
+}
+
static void srp_rport_release(struct device *dev)
{
struct srp_rport *rport = dev_to_rport(dev);
+ cancel_delayed_work_sync(&rport->reconnect_work);
+ cancel_delayed_work_sync(&rport->fast_io_fail_work);
+ cancel_delayed_work_sync(&rport->dev_loss_work);
+
put_device(dev->parent);
kfree(rport);
}
@@ -214,12 +658,15 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost,
{
struct srp_rport *rport;
struct device *parent = &shost->shost_gendev;
+ struct srp_internal *i = to_srp_internal(shost->transportt);
int id, ret;
rport = kzalloc(sizeof(*rport), GFP_KERNEL);
if (!rport)
return ERR_PTR(-ENOMEM);
+ mutex_init(&rport->mutex);
+
device_initialize(&rport->dev);
rport->dev.parent = get_device(parent);
@@ -228,6 +675,17 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost,
memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id));
rport->roles = ids->roles;
+ if (i->f->reconnect)
+ rport->reconnect_delay = i->f->reconnect_delay ?
+ *i->f->reconnect_delay : 10;
+ INIT_DELAYED_WORK(&rport->reconnect_work, srp_reconnect_work);
+ rport->fast_io_fail_tmo = i->f->fast_io_fail_tmo ?
+ *i->f->fast_io_fail_tmo : 15;
+ rport->dev_loss_tmo = i->f->dev_loss_tmo ? *i->f->dev_loss_tmo : 600;
+ INIT_DELAYED_WORK(&rport->fast_io_fail_work,
+ rport_fast_io_fail_timedout);
+ INIT_DELAYED_WORK(&rport->dev_loss_work, rport_dev_loss_timedout);
+
id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id);
dev_set_name(&rport->dev, "port-%d:%d", shost->host_no, id);
@@ -277,6 +735,12 @@ void srp_rport_del(struct srp_rport *rport)
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
+
+ mutex_lock(&rport->mutex);
+ if (rport->state == SRP_RPORT_BLOCKED)
+ __rport_fast_io_fail_timedout(rport);
+ mutex_unlock(&rport->mutex);
+
put_device(dev);
}
EXPORT_SYMBOL_GPL(srp_rport_del);
@@ -328,6 +792,8 @@ srp_attach_transport(struct srp_function_template *ft)
if (!i)
return NULL;
+ i->t.eh_timed_out = srp_timed_out;
+
i->t.tsk_mgmt_response = srp_tsk_mgmt_response;
i->t.it_nexus_response = srp_it_nexus_response;
@@ -345,6 +811,15 @@ srp_attach_transport(struct srp_function_template *ft)
count = 0;
i->rport_attrs[count++] = &dev_attr_port_id;
i->rport_attrs[count++] = &dev_attr_roles;
+ if (ft->has_rport_state) {
+ i->rport_attrs[count++] = &dev_attr_state;
+ i->rport_attrs[count++] = &dev_attr_fast_io_fail_tmo;
+ i->rport_attrs[count++] = &dev_attr_dev_loss_tmo;
+ }
+ if (ft->reconnect) {
+ i->rport_attrs[count++] = &dev_attr_reconnect_delay;
+ i->rport_attrs[count++] = &dev_attr_failed_reconnects;
+ }
if (ft->rport_delete)
i->rport_attrs[count++] = &dev_attr_delete;
i->rport_attrs[count++] = NULL;
diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h
index 5a2d2d1..fbcc985 100644
--- a/include/scsi/scsi_transport_srp.h
+++ b/include/scsi/scsi_transport_srp.h
@@ -13,6 +13,26 @@ struct srp_rport_identifiers {
u8 roles;
};
+/**
+ * enum srp_rport_state - SRP transport layer state
+ * @SRP_RPORT_RUNNING: Transport layer operational.
+ * @SRP_RPORT_BLOCKED: Transport layer not operational; fast I/O fail timer
+ * is running and I/O has been blocked.
+ * @SRP_RPORT_FAIL_FAST: Fast I/O fail timer has expired; fail I/O fast.
+ * @SRP_RPORT_LOST: Device loss timer has expired; port is being removed.
+ */
+enum srp_rport_state {
+ SRP_RPORT_RUNNING,
+ SRP_RPORT_BLOCKED,
+ SRP_RPORT_FAIL_FAST,
+ SRP_RPORT_LOST,
+};
+
+/**
+ * struct srp_rport
+ * @mutex: Protects against concurrent rport fast_io_fail / dev_loss_tmo /
+ * reconnect activity.
+ */
struct srp_rport {
/* for initiator and target drivers */
@@ -23,11 +43,27 @@ struct srp_rport {
/* for initiator drivers */
- void *lld_data; /* LLD private data */
+ void *lld_data; /* LLD private data */
+
+ struct mutex mutex;
+ enum srp_rport_state state;
+ int reconnect_delay;
+ int failed_reconnects;
+ struct delayed_work reconnect_work;
+ int fast_io_fail_tmo;
+ int dev_loss_tmo;
+ struct delayed_work fast_io_fail_work;
+ struct delayed_work dev_loss_work;
};
struct srp_function_template {
/* for initiator drivers */
+ bool has_rport_state;
+ int *reconnect_delay;
+ int *fast_io_fail_tmo;
+ int *dev_loss_tmo;
+ int (*reconnect)(struct srp_rport *rport);
+ void (*terminate_rport_io)(struct srp_rport *rport);
void (*rport_delete)(struct srp_rport *rport);
/* for target drivers */
int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
@@ -43,7 +79,29 @@ extern void srp_rport_put(struct srp_rport *rport);
extern struct srp_rport *srp_rport_add(struct Scsi_Host *,
struct srp_rport_identifiers *);
extern void srp_rport_del(struct srp_rport *);
-
+extern int srp_tmo_valid(int fast_io_fail_tmo, int dev_loss_tmo);
+extern int srp_reconnect_rport(struct srp_rport *rport);
+extern void srp_start_tl_fail_timers(struct srp_rport *rport);
extern void srp_remove_host(struct Scsi_Host *);
+/**
+ * srp_chkready() - evaluate the transport layer state before I/O
+ *
+ * Returns a SCSI result code that can be returned by the LLD. The role of
+ * this function is similar to that of fc_remote_port_chkready().
+ */
+static inline int srp_chkready(struct srp_rport *rport)
+{
+ switch (rport->state) {
+ case SRP_RPORT_RUNNING:
+ case SRP_RPORT_BLOCKED:
+ default:
+ return 0;
+ case SRP_RPORT_FAIL_FAST:
+ return DID_TRANSPORT_FAILFAST << 16;
+ case SRP_RPORT_LOST:
+ return DID_NO_CONNECT << 16;
+ }
+}
+
#endif
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 12/15] IB/srp: Fail SCSI commands silently
2013-06-28 12:45 [PATCH v2 0/15] IB SRP initiator patches for kernel 3.11 Bart Van Assche
[not found] ` <51CD856A.3010102-HInyCGIudOg@public.gmane.org>
2013-06-28 12:53 ` [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling Bart Van Assche
@ 2013-06-28 12:56 ` Bart Van Assche
[not found] ` <51CD8812.20107-HInyCGIudOg@public.gmane.org>
2 siblings, 1 reply; 11+ messages in thread
From: Bart Van Assche @ 2013-06-28 12:56 UTC (permalink / raw)
To: Roland Dreier
Cc: David Dillow, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi
From: Sebastian Riemer <sebastian.riemer@profitbricks.com>
Avoid that path failover in a multipath setup causes the SCSI layer
to generate kernel messages about SCSI command failures. This patch
speeds up SRP initiator operation significantly when monitoring
kernel messages over a serial port.
[bvanassche: Changed patch description]
Signed-off-by: Sebastian Riemer <sebastian.riemer@profitbricks.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Roland Dreier <roland@purestorage.com>
Cc: David Dillow <dillowda@ornl.gov>
Cc: Vu Pham <vu@mellanox.com>
---
drivers/infiniband/ulp/srp/ib_srp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index a8cc427..e77176e 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -757,6 +757,7 @@ static void srp_finish_req(struct srp_target_port *target,
if (scmnd) {
srp_free_req(target, req, scmnd, 0);
+ scmnd->request->cmd_flags |= REQ_QUIET;
scmnd->result = result;
scmnd->scsi_done(scmnd);
}
@@ -1438,6 +1439,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
result = srp_chkready(target->rport);
if (unlikely(result)) {
+ scmnd->request->cmd_flags |= REQ_QUIET;
scmnd->result = result;
scmnd->scsi_done(scmnd);
return 0;
@@ -1843,6 +1845,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
else
ret = FAILED;
srp_free_req(target, req, scmnd, 0);
+ scmnd->request->cmd_flags |= REQ_QUIET;
scmnd->result = DID_ABORT << 16;
scmnd->scsi_done(scmnd);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 06/15] IB/srp: Maintain a single connection per I_T nexus
[not found] ` <51CD86CE.8080804-HInyCGIudOg@public.gmane.org>
@ 2013-06-30 20:10 ` David Dillow
0 siblings, 0 replies; 11+ messages in thread
From: David Dillow @ 2013-06-30 20:10 UTC (permalink / raw)
To: Bart Van Assche
Cc: Roland Dreier, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi
On Fri, 2013-06-28 at 14:51 +0200, Bart Van Assche wrote:
> An SRP target is required to maintain a single connection between
> initiator and target. This means that if the 'add_target' attribute
> is used to create a second connection to a target that the first
> connection will be logged out and that the SCSI error handler will
> kick in. The SCSI error handler will cause the SRP initiator to
> reconnect, which will cause I/O over the second connection to fail.
> Avoid such ping-pong behavior by disabling relogins. Note: if
> reconnecting manually is necessary, that is possible by deleting
> and recreating an rport via sysfs.
Acked-by: David Dillow <dillowda-1Heg1YXhbW8@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling
2013-06-28 12:53 ` [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling Bart Van Assche
@ 2013-06-30 21:05 ` David Dillow
[not found] ` <1372626334.12468.34.camel-a7a0dvSY7KqLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: David Dillow @ 2013-06-30 21:05 UTC (permalink / raw)
To: Bart Van Assche
Cc: Roland Dreier, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi,
James Bottomley
On Fri, 2013-06-28 at 14:53 +0200, Bart Van Assche wrote:
> Add the necessary functions in the SRP transport module to allow
> an SRP initiator driver to implement transport layer error handling
> similar to the functionality already provided by the FC transport
> layer. This includes:
> - Support for implementing fast_io_fail_tmo, the time that should
> elapse after having detected a transport layer problem and
> before failing I/O.
> - Support for implementing dev_loss_tmo, the time that should
> elapse after having detected a transport layer problem and
> before removing a remote port.
>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> Cc: Roland Dreier <roland@purestorage.com>
> Cc: James Bottomley <JBottomley@Parallels.com>
> Cc: David Dillow <dillowda@ornl.gov>
> Cc: Vu Pham <vu@mellanox.com>
> Cc: Sebastian Riemer <sebastian.riemer@profitbricks.com>
> ---
> Documentation/ABI/stable/sysfs-transport-srp | 37 ++
> drivers/scsi/scsi_transport_srp.c | 477 +++++++++++++++++++++++++-
> include/scsi/scsi_transport_srp.h | 62 +++-
> 3 files changed, 573 insertions(+), 3 deletions(-)
> +/**
> + * srp_tmo_valid() - check timeout combination validity
> + *
> + * If both a fast I/O fail and a device loss timeout have been configured then
> + * the fast I/O fail timeout must be below the device loss timeout.
> + */
> +int srp_tmo_valid(int fast_io_fail_tmo, int dev_loss_tmo)
> +{
> + return (fast_io_fail_tmo < 0 || dev_loss_tmo < 0 ||
> + fast_io_fail_tmo < dev_loss_tmo) &&
> + fast_io_fail_tmo < LONG_MAX / HZ &&
> + dev_loss_tmo < LONG_MAX / HZ ? 0 : -EINVAL;
> +}
There's really no need to fit it in one line to save space -- it makes
it much easier to read if you unpack it and return -EINVAL for the
problem cases.
They should also be capped by SCSI_DEVICE_BLOCK_MAX_TIMEOUT instead of
LONG_MAX / HZ, I think.
> +static ssize_t store_reconnect_delay(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, const size_t count)
> +{
> + struct srp_rport *rport = transport_class_to_srp_rport(dev);
> + char ch[16];
> + int res, delay;
> +
> + sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
> + res = kstrtoint(ch, 0, &delay);
> + if (res)
> + goto out;
I don't see the need for the sprintf? kstrtoint() will give you -ERANGE
if the value doesn't fit in an int...
Ah, NULL terminated string... except sysfs guarantees this for us for
the store method -- see fill_write_buffer() in fs/sysfs.c.
> +static ssize_t store_srp_rport_fast_io_fail_tmo(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct srp_rport *rport = transport_class_to_srp_rport(dev);
> + char ch[16], *p;
> + int res;
> + int fast_io_fail_tmo;
> +
> + sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
> + p = strchr(ch, '\n');
> + if (p)
> + *p = '\0';
Again, no need for the sprintf if you don't modify the buffer? Instead
of using strchr() to make the strcmp() work with newlines, just do
if (!strcmp(buf, "off") || !strcmp(buf, "off\n")) {
fast_io_fail_tmo = 1;
} else {
res = kstrtoint(buf, 0, &fast_io_fail_tmo);
...
instead?
Same comment applies for store_srp_rport_dev_loss_tmo().
I haven't fully gone over the logic just yet, so I'm relying a bit on
Hannes and Mike's discussion from the last round. This looks to be
pretty reasonably sorted, though, based on the level of review I've been
able to do so far...
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 07/15] IB/srp: Keep rport as long as the IB transport layer
2013-06-28 12:52 ` [PATCH v2 07/15] IB/srp: Keep rport as long as the IB transport layer Bart Van Assche
@ 2013-06-30 21:06 ` David Dillow
0 siblings, 0 replies; 11+ messages in thread
From: David Dillow @ 2013-06-30 21:06 UTC (permalink / raw)
To: Bart Van Assche
Cc: Roland Dreier, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi,
James Bottomley
On Fri, 2013-06-28 at 14:52 +0200, Bart Van Assche wrote:
> Keep the rport data structure around after srp_remove_host() has
> finished until cleanup of the IB transport layer has finished
> completely. This is necessary because later patches use the rport
> pointer inside the queuecommand callback. Without this patch
> accessing the rport from inside a queuecommand callback is racy
> because srp_remove_host() must be invoked before scsi_remove_host()
> and because the queuecommand callback may get invoked after
> srp_remove_host() has finished.
Assuming the patches that require this are eventually accepted,
Acked-by: David Dillow <dillowda@ornl.gov>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 12/15] IB/srp: Fail SCSI commands silently
[not found] ` <51CD8812.20107-HInyCGIudOg@public.gmane.org>
@ 2013-06-30 21:25 ` David Dillow
0 siblings, 0 replies; 11+ messages in thread
From: David Dillow @ 2013-06-30 21:25 UTC (permalink / raw)
To: Bart Van Assche
Cc: Roland Dreier, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi
On Fri, 2013-06-28 at 14:56 +0200, Bart Van Assche wrote:
> From: Sebastian Riemer <sebastian.riemer-EIkl63zCoXaH+58JC4qpiA@public.gmane.org>
>
> Avoid that path failover in a multipath setup causes the SCSI layer
> to generate kernel messages about SCSI command failures. This patch
> speeds up SRP initiator operation significantly when monitoring
> kernel messages over a serial port.
I'm not sure this should be fixed in the drivers -- this seems like an
issue that should be handled/configured in the core based on the host
result code.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling
[not found] ` <1372626334.12468.34.camel-a7a0dvSY7KqLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
@ 2013-07-01 7:01 ` Bart Van Assche
[not found] ` <51D12941.3050105-HInyCGIudOg@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Bart Van Assche @ 2013-07-01 7:01 UTC (permalink / raw)
To: David Dillow
Cc: Roland Dreier, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi,
James Bottomley
On 06/30/13 23:05, David Dillow wrote:
> On Fri, 2013-06-28 at 14:53 +0200, Bart Van Assche wrote:
>> +int srp_tmo_valid(int fast_io_fail_tmo, int dev_loss_tmo)
>> +{
>> + return (fast_io_fail_tmo < 0 || dev_loss_tmo < 0 ||
>> + fast_io_fail_tmo < dev_loss_tmo) &&
>> + fast_io_fail_tmo < LONG_MAX / HZ &&
>> + dev_loss_tmo < LONG_MAX / HZ ? 0 : -EINVAL;
>> +}
>
> They should also be capped by SCSI_DEVICE_BLOCK_MAX_TIMEOUT instead of
> LONG_MAX / HZ, I think.
The fast_io_fail_tmo should indeed be capped by that value. However, I'm
not sure about dev_loss_tmo. I think there are several use cases (e.g.
initiator-side mirroring) where it's useful to set dev_loss_tmo to a
larger value than ten minutes.
>> +static ssize_t store_srp_rport_fast_io_fail_tmo(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct srp_rport *rport = transport_class_to_srp_rport(dev);
>> + char ch[16], *p;
>> + int res;
>> + int fast_io_fail_tmo;
>> +
>> + sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
>> + p = strchr(ch, '\n');
>> + if (p)
>> + *p = '\0';
>
> Again, no need for the sprintf if you don't modify the buffer? Instead
> of using strchr() to make the strcmp() work with newlines, just do
>
> if (!strcmp(buf, "off") || !strcmp(buf, "off\n")) {
> fast_io_fail_tmo = 1;
> } else {
> res = kstrtoint(buf, 0, &fast_io_fail_tmo);
> ...
>
> instead?
>
> Same comment applies for store_srp_rport_dev_loss_tmo().
OK, will remove the temporary char arrays.
Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling
[not found] ` <51D12941.3050105-HInyCGIudOg@public.gmane.org>
@ 2013-07-01 11:19 ` David Dillow
0 siblings, 0 replies; 11+ messages in thread
From: David Dillow @ 2013-07-01 11:19 UTC (permalink / raw)
To: Bart Van Assche
Cc: Roland Dreier, Vu Pham, Sebastian Riemer, linux-rdma, linux-scsi,
James Bottomley
On Mon, 2013-07-01 at 09:01 +0200, Bart Van Assche wrote:
> On 06/30/13 23:05, David Dillow wrote:
> > On Fri, 2013-06-28 at 14:53 +0200, Bart Van Assche wrote:
> >> +int srp_tmo_valid(int fast_io_fail_tmo, int dev_loss_tmo)
> >> +{
> >> + return (fast_io_fail_tmo < 0 || dev_loss_tmo < 0 ||
> >> + fast_io_fail_tmo < dev_loss_tmo) &&
> >> + fast_io_fail_tmo < LONG_MAX / HZ &&
> >> + dev_loss_tmo < LONG_MAX / HZ ? 0 : -EINVAL;
> >> +}
> >
> > They should also be capped by SCSI_DEVICE_BLOCK_MAX_TIMEOUT instead of
> > LONG_MAX / HZ, I think.
>
> The fast_io_fail_tmo should indeed be capped by that value. However, I'm
> not sure about dev_loss_tmo. I think there are several use cases (e.g.
> initiator-side mirroring) where it's useful to set dev_loss_tmo to a
> larger value than ten minutes.
Ah, yes, very good point.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2013-07-01 11:19 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-28 12:45 [PATCH v2 0/15] IB SRP initiator patches for kernel 3.11 Bart Van Assche
[not found] ` <51CD856A.3010102-HInyCGIudOg@public.gmane.org>
2013-06-28 12:51 ` [PATCH v2 06/15] IB/srp: Maintain a single connection per I_T nexus Bart Van Assche
[not found] ` <51CD86CE.8080804-HInyCGIudOg@public.gmane.org>
2013-06-30 20:10 ` David Dillow
2013-06-28 12:52 ` [PATCH v2 07/15] IB/srp: Keep rport as long as the IB transport layer Bart Van Assche
2013-06-30 21:06 ` David Dillow
2013-06-28 12:53 ` [PATCH v2 08/15] scsi_transport_srp: Add transport layer error handling Bart Van Assche
2013-06-30 21:05 ` David Dillow
[not found] ` <1372626334.12468.34.camel-a7a0dvSY7KqLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
2013-07-01 7:01 ` Bart Van Assche
[not found] ` <51D12941.3050105-HInyCGIudOg@public.gmane.org>
2013-07-01 11:19 ` David Dillow
2013-06-28 12:56 ` [PATCH v2 12/15] IB/srp: Fail SCSI commands silently Bart Van Assche
[not found] ` <51CD8812.20107-HInyCGIudOg@public.gmane.org>
2013-06-30 21:25 ` David Dillow
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox