* [PATCH 0/3] zfcp features for 3.19
@ 2014-11-13 13:59 Steffen Maier
2014-11-13 13:59 ` [PATCH 1/3] zfcp: remove access control tables interface (port leftovers) Steffen Maier
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Steffen Maier @ 2014-11-13 13:59 UTC (permalink / raw)
To: James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Steffen Maier
James,
Here is a series of zfcp features for the upcoming merge window
preparing kernel v3.19.
The patches apply on top of the current misc branch of your scsi.git.
Steffen
Linux on System z Development
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294
Martin Peschke (2):
zfcp: remove access control tables interface (port leftovers)
zfcp: auto port scan resiliency
Steffen Maier (1):
zfcp: bring back unit sysfs attributes for automatic LUN scan
drivers/s390/scsi/zfcp_aux.c | 6 ++--
drivers/s390/scsi/zfcp_ccw.c | 32 ++++++++++++++++----
drivers/s390/scsi/zfcp_def.h | 3 +-
drivers/s390/scsi/zfcp_erp.c | 7 -----
drivers/s390/scsi/zfcp_ext.h | 1 +
drivers/s390/scsi/zfcp_fc.c | 52 +++++++++++++++++++++++++++++++--
drivers/s390/scsi/zfcp_fsf.c | 3 +-
drivers/s390/scsi/zfcp_sysfs.c | 66 ++++++++++++++++++++++++++++++++++++------
8 files changed, 141 insertions(+), 29 deletions(-)
--
1.8.5.5
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] zfcp: remove access control tables interface (port leftovers)
2014-11-13 13:59 [PATCH 0/3] zfcp features for 3.19 Steffen Maier
@ 2014-11-13 13:59 ` Steffen Maier
2014-11-17 13:29 ` Hannes Reinecke
2014-11-13 13:59 ` [PATCH 2/3] zfcp: bring back unit sysfs attributes for automatic LUN scan Steffen Maier
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Steffen Maier @ 2014-11-13 13:59 UTC (permalink / raw)
To: James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Steffen Maier, Martin Peschke
From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
This patch removes some leftovers for commit
663e0890e31cb85f0cca5ac1faaee0d2d52880b5
"[SCSI] zfcp: remove access control tables interface".
The "access denied" case for ports is gone, as well.
The corresponding flag was cleared, but never set.
So clean it up.
Sysfs flag is kept, though, for backward-compatibility.
Now it returns always 0.
Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
---
drivers/s390/scsi/zfcp_erp.c | 7 -------
drivers/s390/scsi/zfcp_fsf.c | 3 +--
drivers/s390/scsi/zfcp_sysfs.c | 4 +---
3 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index c82fe65..2c5d456 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -821,11 +821,6 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
return ZFCP_ERP_CONTINUES;
}
-static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
-{
- atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
-}
-
static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
{
struct zfcp_port *port = erp_action->port;
@@ -833,7 +828,6 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
- zfcp_erp_port_strategy_clearstati(port);
if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
(status & ZFCP_STATUS_COMMON_OPEN))
return zfcp_erp_port_forced_strategy_close(erp_action);
@@ -933,7 +927,6 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
- zfcp_erp_port_strategy_clearstati(port);
if (p_status & ZFCP_STATUS_COMMON_OPEN)
return zfcp_erp_port_strategy_close(erp_action);
break;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 0fe8d5d..21ec5e2 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1396,8 +1396,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
port->handle = header->port_handle;
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
- atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
&port->status);
/* check whether D_ID has changed during open */
/*
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 672b572..6b66412 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -73,9 +73,7 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
(atomic_read(&port->status) &
ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
-ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
- (atomic_read(&port->status) &
- ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+ZFCP_DEFINE_ATTR_CONST(port, access_denied, "%d\n", 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
zfcp_unit_sdev_status(unit));
--
1.8.5.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] zfcp: bring back unit sysfs attributes for automatic LUN scan
2014-11-13 13:59 [PATCH 0/3] zfcp features for 3.19 Steffen Maier
2014-11-13 13:59 ` [PATCH 1/3] zfcp: remove access control tables interface (port leftovers) Steffen Maier
@ 2014-11-13 13:59 ` Steffen Maier
2014-11-17 13:34 ` Hannes Reinecke
2014-11-13 13:59 ` [PATCH 3/3] zfcp: auto port scan resiliency Steffen Maier
2014-11-20 15:52 ` [PATCH 0/3] zfcp features for 3.19 Christoph Hellwig
3 siblings, 1 reply; 9+ messages in thread
From: Steffen Maier @ 2014-11-13 13:59 UTC (permalink / raw)
To: James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Steffen Maier
Through sysfs attributes, zfcp unit objects
provide a trigger for manual LUN recovery
and export information for problem determination.
With commit
f8210e34887e1feb977a9b6b8caa086855af40c9
"[SCSI] zfcp: Allow midlayer to scan for LUNs when running in NPIV mode"
and when attaching SCSI devices through this new optional method,
no more zfcp unit objects are allocated for such SCSI devices.
Hence, the above-mentioned trigger and information were missing.
The information and context is located in SCSI transport device data since
b62a8d9b45b971a67a0f8413338c230e3117dff5
"[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit"
57c237731b92fadc7d44824276313ec330b1989b
"[SCSI] zfcp: Add zfcp private struct as SCSI device driver data"
Hence, introduce the trigger and the information unconditionally
for all SCSI devices attached through zfcp.
We prefix the attribute names with 'zfcp_' to prevent collisions and
to avoid mix-ups such as with the common 'state' attribute.
Since some of the new attribute views do not need zfcp_port
in the ZFCP_DEFINE_SCSI_ATTR helper macro, remove zfcp_port
to avoid compiler warnings on unused variable.
It's easy to open code the conversion from zfcp_scsi_dev to zfcp_port
for the two already existing attributes hba_id and wwpn.
Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
Reviewed-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
---
drivers/s390/scsi/zfcp_sysfs.c | 52 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 6b66412..a488c09 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -437,16 +437,15 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
{ \
struct scsi_device *sdev = to_scsi_device(dev); \
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
- struct zfcp_port *port = zfcp_sdev->port; \
\
return sprintf(buf, _format, _value); \
} \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
- dev_name(&port->adapter->ccw_device->dev));
+ dev_name(&zfcp_sdev->port->adapter->ccw_device->dev));
ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
- (unsigned long long) port->wwpn);
+ (unsigned long long) zfcp_sdev->port->wwpn);
static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
struct device_attribute *attr,
@@ -458,6 +457,49 @@ static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
}
static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
+ZFCP_DEFINE_SCSI_ATTR(zfcp_access_denied, "%d\n",
+ (atomic_read(&zfcp_sdev->status) &
+ ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+
+static ssize_t zfcp_sysfs_scsi_zfcp_failed_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ unsigned int status = atomic_read(&sdev_to_zfcp(sdev)->status);
+ unsigned int failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
+
+ return sprintf(buf, "%d\n", failed);
+}
+
+static ssize_t zfcp_sysfs_scsi_zfcp_failed_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ unsigned long val;
+
+ if (kstrtoul(buf, 0, &val) || val != 0)
+ return -EINVAL;
+
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+ zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "syufai3");
+ zfcp_erp_wait(sdev_to_zfcp(sdev)->port->adapter);
+
+ return count;
+}
+static DEVICE_ATTR(zfcp_failed, S_IWUSR | S_IRUGO,
+ zfcp_sysfs_scsi_zfcp_failed_show,
+ zfcp_sysfs_scsi_zfcp_failed_store);
+
+ZFCP_DEFINE_SCSI_ATTR(zfcp_in_recovery, "%d\n",
+ (atomic_read(&zfcp_sdev->status) &
+ ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
+
+ZFCP_DEFINE_SCSI_ATTR(zfcp_status, "0x%08x\n",
+ atomic_read(&zfcp_sdev->status));
+
struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
&dev_attr_wwpn,
@@ -465,6 +507,10 @@ struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_read_latency,
&dev_attr_write_latency,
&dev_attr_cmd_latency,
+ &dev_attr_zfcp_access_denied,
+ &dev_attr_zfcp_failed,
+ &dev_attr_zfcp_in_recovery,
+ &dev_attr_zfcp_status,
NULL
};
--
1.8.5.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/3] zfcp: auto port scan resiliency
2014-11-13 13:59 [PATCH 0/3] zfcp features for 3.19 Steffen Maier
2014-11-13 13:59 ` [PATCH 1/3] zfcp: remove access control tables interface (port leftovers) Steffen Maier
2014-11-13 13:59 ` [PATCH 2/3] zfcp: bring back unit sysfs attributes for automatic LUN scan Steffen Maier
@ 2014-11-13 13:59 ` Steffen Maier
2014-11-17 13:37 ` Hannes Reinecke
2014-11-20 15:52 ` [PATCH 0/3] zfcp features for 3.19 Christoph Hellwig
3 siblings, 1 reply; 9+ messages in thread
From: Steffen Maier @ 2014-11-13 13:59 UTC (permalink / raw)
To: James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Steffen Maier, Martin Peschke
From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
This patch improves the Fibre Channel port scan behaviour of the zfcp lldd.
Without it the zfcp device driver may churn up the storage area network by
excessive scanning and scan bursts, particularly in big virtual server
environments, potentially resulting in interference of virtual servers and
reduced availability of storage connectivity.
The two main issues as to the zfcp device drivers automatic port scan in
virtual server environments are frequency and simultaneity.
On the one hand, there is no point in allowing lots of ports scans
in a row. It makes sense, though, to make sure that a scan is conducted
eventually if there has been any indication for potential SAN changes.
On the other hand, lots of virtual servers receiving the same indication
for a SAN change had better not attempt to conduct a scan instantly,
that is, at the same time.
Hence this patch has a two-fold approach for better port scanning:
the introduction of a rate limit to amend frequency issues, and the
introduction of a short random backoff to amend simultaneity issues.
Both approaches boil down to deferred port scans, with delays
comprising parts for both approaches.
The new port scan behaviour is summarised best by:
NEW: NEW:
no_auto_port_rescan random rate flush
backoff limit =wait
adapter resume/thaw yes yes no yes*
adapter online (user) no yes no yes*
port rescan (user) no no no yes
adapter recovery (user) yes yes yes no
adapter recovery (other) yes yes yes no
incoming ELS yes yes yes no
incoming ELS lost yes yes yes no
Implementation is straight-forward by converting an existing worker to
a delayed worker. But care is needed whenever that worker is going to be
flushed (in order to make sure work has been completed), since a flush
operation cancels the timer set up for deferred execution (see * above).
There is a small race window whenever a port scan work starts
running up to the point in time of storing the time stamp for that port
scan. The impact is negligible. Closing that gap isn't trivial, though, and
would the destroy the beauty of a simple work-to-delayed-work conversion.
Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
---
drivers/s390/scsi/zfcp_aux.c | 6 +++--
drivers/s390/scsi/zfcp_ccw.c | 32 ++++++++++++++++++++++----
drivers/s390/scsi/zfcp_def.h | 3 ++-
drivers/s390/scsi/zfcp_ext.h | 1 +
drivers/s390/scsi/zfcp_fc.c | 52 +++++++++++++++++++++++++++++++++++++++---
drivers/s390/scsi/zfcp_sysfs.c | 10 +++++---
6 files changed, 90 insertions(+), 14 deletions(-)
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 8004b07..01a7339 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -353,9 +353,11 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
adapter->ccw_device = ccw_device;
INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
- INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
+ INIT_DELAYED_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
+ adapter->next_port_scan = jiffies;
+
if (zfcp_qdio_setup(adapter))
goto failed;
@@ -420,7 +422,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
{
struct ccw_device *cdev = adapter->ccw_device;
- cancel_work_sync(&adapter->scan_work);
+ cancel_delayed_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
cancel_work_sync(&adapter->ns_up_work);
zfcp_destroy_adapter_work_queue(adapter);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index f9879d4..54c7b48 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -56,8 +56,22 @@ static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
tag);
+
+ /*
+ * We want to scan ports here, with some random backoff and without
+ * rate limit. Recovery has already scheduled a port scan for us,
+ * but with both random delay and rate limit. Nevertheless we get
+ * what we want here by flushing the scheduled work after sleeping
+ * an equivalent random time.
+ * Let the port scan random delay elapse first. If recovery finishes
+ * up to that point in time, that would be perfect for both recovery
+ * and port scan. If not, i.e. recovery takes ages, there was no
+ * point in waiting a random delay on top of the time consumed by
+ * recovery.
+ */
+ msleep(zfcp_fc_port_scan_backoff());
zfcp_erp_wait(adapter);
- flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
+ flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter);
@@ -162,11 +176,19 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
adapter->req_no = 0;
zfcp_ccw_activate(cdev, 0, "ccsonl1");
- /* scan for remote ports
- either at the end of any successful adapter recovery
- or only after the adapter recovery for setting a device online */
+
+ /*
+ * We want to scan ports here, always, with some random delay and
+ * without rate limit - basically what zfcp_ccw_activate() has
+ * achieved for us. Not quite! That port scan depended on
+ * !no_auto_port_rescan. So let's cover the no_auto_port_rescan
+ * case here to make sure a port scan is done unconditionally.
+ * Since zfcp_ccw_activate() has waited the desired random time,
+ * we can immediately schedule and flush a port scan for the
+ * remaining cases.
+ */
zfcp_fc_inverse_conditional_port_scan(adapter);
- flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
+ flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter);
return 0;
}
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d91173f..b8e853e 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -186,12 +186,13 @@ struct zfcp_adapter {
struct fc_host_statistics *fc_stats;
struct fsf_qtcb_bottom_port *stats_reset_data;
unsigned long stats_reset;
- struct work_struct scan_work;
+ struct delayed_work scan_work;
struct work_struct ns_up_work;
struct service_level service_level;
struct workqueue_struct *work_queue;
struct device_dma_parameters dma_parms;
struct zfcp_fc_events events;
+ unsigned long next_port_scan;
};
struct zfcp_port {
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index a9c570a..5b50065 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -85,6 +85,7 @@ extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
extern void zfcp_fc_sym_name_update(struct work_struct *);
+extern unsigned int zfcp_fc_port_scan_backoff(void);
extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
extern void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index ca28e1c..25d49f3 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/utsname.h>
+#include <linux/random.h>
#include <scsi/fc/fc_els.h>
#include <scsi/libfc.h>
#include "zfcp_ext.h"
@@ -31,12 +32,54 @@ module_param_named(no_auto_port_rescan, no_auto_port_rescan, bool, 0600);
MODULE_PARM_DESC(no_auto_port_rescan,
"no automatic port_rescan (default off)");
+static unsigned int port_scan_backoff = 500;
+module_param(port_scan_backoff, uint, 0600);
+MODULE_PARM_DESC(port_scan_backoff,
+ "upper limit of port scan random backoff in msecs (default 500)");
+
+static unsigned int port_scan_ratelimit = 60000;
+module_param(port_scan_ratelimit, uint, 0600);
+MODULE_PARM_DESC(port_scan_ratelimit,
+ "minimum interval between port scans in msecs (default 60000)");
+
+unsigned int zfcp_fc_port_scan_backoff(void)
+{
+ if (!port_scan_backoff)
+ return 0;
+ return get_random_int() % port_scan_backoff;
+}
+
+static void zfcp_fc_port_scan_time(struct zfcp_adapter *adapter)
+{
+ unsigned long interval = msecs_to_jiffies(port_scan_ratelimit);
+ unsigned long backoff = msecs_to_jiffies(zfcp_fc_port_scan_backoff());
+
+ adapter->next_port_scan = jiffies + interval + backoff;
+}
+
+static void zfcp_fc_port_scan(struct zfcp_adapter *adapter)
+{
+ unsigned long now = jiffies;
+ unsigned long next = adapter->next_port_scan;
+ unsigned long delay = 0, max;
+
+ /* delay only needed within waiting period */
+ if (time_before(now, next)) {
+ delay = next - now;
+ /* paranoia: never ever delay scans longer than specified */
+ max = msecs_to_jiffies(port_scan_ratelimit + port_scan_backoff);
+ delay = min(delay, max);
+ }
+
+ queue_delayed_work(adapter->work_queue, &adapter->scan_work, delay);
+}
+
void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter)
{
if (no_auto_port_rescan)
return;
- queue_work(adapter->work_queue, &adapter->scan_work);
+ zfcp_fc_port_scan(adapter);
}
void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
@@ -44,7 +87,7 @@ void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
if (!no_auto_port_rescan)
return;
- queue_work(adapter->work_queue, &adapter->scan_work);
+ zfcp_fc_port_scan(adapter);
}
/**
@@ -680,12 +723,15 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req,
*/
void zfcp_fc_scan_ports(struct work_struct *work)
{
- struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
+ struct delayed_work *dw = to_delayed_work(work);
+ struct zfcp_adapter *adapter = container_of(dw, struct zfcp_adapter,
scan_work);
int ret, i;
struct zfcp_fc_req *fc_req;
int chain, max_entries, buf_num, max_bytes;
+ zfcp_fc_port_scan_time(adapter);
+
chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
buf_num = chain ? ZFCP_FC_GPN_FT_NUM_BUFS : 1;
max_entries = chain ? ZFCP_FC_GPN_FT_MAX_ENT : ZFCP_FC_GPN_FT_ENT_PAGE;
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index a488c09..96a0be1 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -221,9 +221,13 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
if (!adapter)
return -ENODEV;
- /* sync the user-space- with the kernel-invocation of scan_work */
- queue_work(adapter->work_queue, &adapter->scan_work);
- flush_work(&adapter->scan_work);
+ /*
+ * Users wish is our command: immediately schedule and flush a
+ * worker to conduct a synchronous port scan, that is, neither
+ * a random delay nor a rate limit is applied here.
+ */
+ queue_delayed_work(adapter->work_queue, &adapter->scan_work, 0);
+ flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter);
return (ssize_t) count;
--
1.8.5.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] zfcp: remove access control tables interface (port leftovers)
2014-11-13 13:59 ` [PATCH 1/3] zfcp: remove access control tables interface (port leftovers) Steffen Maier
@ 2014-11-17 13:29 ` Hannes Reinecke
2014-11-17 13:33 ` Hannes Reinecke
0 siblings, 1 reply; 9+ messages in thread
From: Hannes Reinecke @ 2014-11-17 13:29 UTC (permalink / raw)
To: Steffen Maier, James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Martin Peschke
On 11/13/2014 02:59 PM, Steffen Maier wrote:
> From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
>
> This patch removes some leftovers for commit
> 663e0890e31cb85f0cca5ac1faaee0d2d52880b5
> "[SCSI] zfcp: remove access control tables interface".
>
> The "access denied" case for ports is gone, as well.
> The corresponding flag was cleared, but never set.
> So clean it up.
>
> Sysfs flag is kept, though, for backward-compatibility.
> Now it returns always 0.
>
> Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
> Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
> ---
> drivers/s390/scsi/zfcp_erp.c | 7 -------
> drivers/s390/scsi/zfcp_fsf.c | 3 +--
> drivers/s390/scsi/zfcp_sysfs.c | 4 +---
> 3 files changed, 2 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
> index c82fe65..2c5d456 100644
> --- a/drivers/s390/scsi/zfcp_erp.c
> +++ b/drivers/s390/scsi/zfcp_erp.c
> @@ -821,11 +821,6 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
> return ZFCP_ERP_CONTINUES;
> }
>
> -static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
> -{
> - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
> -}
> -
> static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
> {
> struct zfcp_port *port = erp_action->port;
> @@ -833,7 +828,6 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
>
> switch (erp_action->step) {
> case ZFCP_ERP_STEP_UNINITIALIZED:
> - zfcp_erp_port_strategy_clearstati(port);
> if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
> (status & ZFCP_STATUS_COMMON_OPEN))
> return zfcp_erp_port_forced_strategy_close(erp_action);
> @@ -933,7 +927,6 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
>
> switch (erp_action->step) {
> case ZFCP_ERP_STEP_UNINITIALIZED:
> - zfcp_erp_port_strategy_clearstati(port);
> if (p_status & ZFCP_STATUS_COMMON_OPEN)
> return zfcp_erp_port_strategy_close(erp_action);
> break;
> diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
> index 0fe8d5d..21ec5e2 100644
> --- a/drivers/s390/scsi/zfcp_fsf.c
> +++ b/drivers/s390/scsi/zfcp_fsf.c
> @@ -1396,8 +1396,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
> port->handle = header->port_handle;
> atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
> ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
> - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
> - ZFCP_STATUS_COMMON_ACCESS_BOXED,
> + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
> &port->status);
> /* check whether D_ID has changed during open */
> /*
> diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
> index 672b572..6b66412 100644
> --- a/drivers/s390/scsi/zfcp_sysfs.c
> +++ b/drivers/s390/scsi/zfcp_sysfs.c
> @@ -73,9 +73,7 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
> ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
> (atomic_read(&port->status) &
> ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
> -ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
> - (atomic_read(&port->status) &
> - ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
> +ZFCP_DEFINE_ATTR_CONST(port, access_denied, "%d\n", 0);
>
> ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
> zfcp_unit_sdev_status(unit));
>
Is the ZFCP_STATUS_COMMON_ACCESS_DENIED bit still in use somewhere?
If not, shouldn't it be removed altogether?
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] zfcp: remove access control tables interface (port leftovers)
2014-11-17 13:29 ` Hannes Reinecke
@ 2014-11-17 13:33 ` Hannes Reinecke
0 siblings, 0 replies; 9+ messages in thread
From: Hannes Reinecke @ 2014-11-17 13:33 UTC (permalink / raw)
To: Steffen Maier, James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Martin Peschke
On 11/17/2014 02:29 PM, Hannes Reinecke wrote:
> On 11/13/2014 02:59 PM, Steffen Maier wrote:
>> From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
>>
>> This patch removes some leftovers for commit
>> 663e0890e31cb85f0cca5ac1faaee0d2d52880b5
>> "[SCSI] zfcp: remove access control tables interface".
>>
>> The "access denied" case for ports is gone, as well.
>> The corresponding flag was cleared, but never set.
>> So clean it up.
>>
>> Sysfs flag is kept, though, for backward-compatibility.
>> Now it returns always 0.
>>
>> Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
>> Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
>> ---
>> drivers/s390/scsi/zfcp_erp.c | 7 -------
>> drivers/s390/scsi/zfcp_fsf.c | 3 +--
>> drivers/s390/scsi/zfcp_sysfs.c | 4 +---
>> 3 files changed, 2 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
>> index c82fe65..2c5d456 100644
>> --- a/drivers/s390/scsi/zfcp_erp.c
>> +++ b/drivers/s390/scsi/zfcp_erp.c
>> @@ -821,11 +821,6 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
>> return ZFCP_ERP_CONTINUES;
>> }
>>
>> -static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
>> -{
>> - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
>> -}
>> -
>> static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
>> {
>> struct zfcp_port *port = erp_action->port;
>> @@ -833,7 +828,6 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
>>
>> switch (erp_action->step) {
>> case ZFCP_ERP_STEP_UNINITIALIZED:
>> - zfcp_erp_port_strategy_clearstati(port);
>> if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
>> (status & ZFCP_STATUS_COMMON_OPEN))
>> return zfcp_erp_port_forced_strategy_close(erp_action);
>> @@ -933,7 +927,6 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
>>
>> switch (erp_action->step) {
>> case ZFCP_ERP_STEP_UNINITIALIZED:
>> - zfcp_erp_port_strategy_clearstati(port);
>> if (p_status & ZFCP_STATUS_COMMON_OPEN)
>> return zfcp_erp_port_strategy_close(erp_action);
>> break;
>> diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
>> index 0fe8d5d..21ec5e2 100644
>> --- a/drivers/s390/scsi/zfcp_fsf.c
>> +++ b/drivers/s390/scsi/zfcp_fsf.c
>> @@ -1396,8 +1396,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
>> port->handle = header->port_handle;
>> atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
>> ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
>> - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
>> - ZFCP_STATUS_COMMON_ACCESS_BOXED,
>> + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
>> &port->status);
>> /* check whether D_ID has changed during open */
>> /*
>> diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
>> index 672b572..6b66412 100644
>> --- a/drivers/s390/scsi/zfcp_sysfs.c
>> +++ b/drivers/s390/scsi/zfcp_sysfs.c
>> @@ -73,9 +73,7 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
>> ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
>> (atomic_read(&port->status) &
>> ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
>> -ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
>> - (atomic_read(&port->status) &
>> - ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
>> +ZFCP_DEFINE_ATTR_CONST(port, access_denied, "%d\n", 0);
>>
>> ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
>> zfcp_unit_sdev_status(unit));
>>
> Is the ZFCP_STATUS_COMMON_ACCESS_DENIED bit still in use somewhere?
> If not, shouldn't it be removed altogether?
>
Ah. Reading the entire patch series helps.
Ignore this objection.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] zfcp: bring back unit sysfs attributes for automatic LUN scan
2014-11-13 13:59 ` [PATCH 2/3] zfcp: bring back unit sysfs attributes for automatic LUN scan Steffen Maier
@ 2014-11-17 13:34 ` Hannes Reinecke
0 siblings, 0 replies; 9+ messages in thread
From: Hannes Reinecke @ 2014-11-17 13:34 UTC (permalink / raw)
To: Steffen Maier, James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens
On 11/13/2014 02:59 PM, Steffen Maier wrote:
> Through sysfs attributes, zfcp unit objects
> provide a trigger for manual LUN recovery
> and export information for problem determination.
>
> With commit
> f8210e34887e1feb977a9b6b8caa086855af40c9
> "[SCSI] zfcp: Allow midlayer to scan for LUNs when running in NPIV mode"
> and when attaching SCSI devices through this new optional method,
> no more zfcp unit objects are allocated for such SCSI devices.
> Hence, the above-mentioned trigger and information were missing.
>
> The information and context is located in SCSI transport device data since
> b62a8d9b45b971a67a0f8413338c230e3117dff5
> "[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit"
> 57c237731b92fadc7d44824276313ec330b1989b
> "[SCSI] zfcp: Add zfcp private struct as SCSI device driver data"
> Hence, introduce the trigger and the information unconditionally
> for all SCSI devices attached through zfcp.
>
> We prefix the attribute names with 'zfcp_' to prevent collisions and
> to avoid mix-ups such as with the common 'state' attribute.
>
> Since some of the new attribute views do not need zfcp_port
> in the ZFCP_DEFINE_SCSI_ATTR helper macro, remove zfcp_port
> to avoid compiler warnings on unused variable.
> It's easy to open code the conversion from zfcp_scsi_dev to zfcp_port
> for the two already existing attributes hba_id and wwpn.
>
> Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
> Reviewed-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
> ---
> drivers/s390/scsi/zfcp_sysfs.c | 52 +++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
> index 6b66412..a488c09 100644
> --- a/drivers/s390/scsi/zfcp_sysfs.c
> +++ b/drivers/s390/scsi/zfcp_sysfs.c
> @@ -437,16 +437,15 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
> { \
> struct scsi_device *sdev = to_scsi_device(dev); \
> struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
> - struct zfcp_port *port = zfcp_sdev->port; \
> \
> return sprintf(buf, _format, _value); \
> } \
> static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
>
> ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
> - dev_name(&port->adapter->ccw_device->dev));
> + dev_name(&zfcp_sdev->port->adapter->ccw_device->dev));
> ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
> - (unsigned long long) port->wwpn);
> + (unsigned long long) zfcp_sdev->port->wwpn);
>
> static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
> struct device_attribute *attr,
> @@ -458,6 +457,49 @@ static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
> }
> static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
>
> +ZFCP_DEFINE_SCSI_ATTR(zfcp_access_denied, "%d\n",
> + (atomic_read(&zfcp_sdev->status) &
> + ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
> +
> +static ssize_t zfcp_sysfs_scsi_zfcp_failed_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct scsi_device *sdev = to_scsi_device(dev);
> + unsigned int status = atomic_read(&sdev_to_zfcp(sdev)->status);
> + unsigned int failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
> +
> + return sprintf(buf, "%d\n", failed);
> +}
> +
> +static ssize_t zfcp_sysfs_scsi_zfcp_failed_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct scsi_device *sdev = to_scsi_device(dev);
> + unsigned long val;
> +
> + if (kstrtoul(buf, 0, &val) || val != 0)
> + return -EINVAL;
> +
> + zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
> + zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
> + "syufai3");
> + zfcp_erp_wait(sdev_to_zfcp(sdev)->port->adapter);
> +
> + return count;
> +}
> +static DEVICE_ATTR(zfcp_failed, S_IWUSR | S_IRUGO,
> + zfcp_sysfs_scsi_zfcp_failed_show,
> + zfcp_sysfs_scsi_zfcp_failed_store);
> +
> +ZFCP_DEFINE_SCSI_ATTR(zfcp_in_recovery, "%d\n",
> + (atomic_read(&zfcp_sdev->status) &
> + ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
> +
> +ZFCP_DEFINE_SCSI_ATTR(zfcp_status, "0x%08x\n",
> + atomic_read(&zfcp_sdev->status));
> +
> struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
> &dev_attr_fcp_lun,
> &dev_attr_wwpn,
> @@ -465,6 +507,10 @@ struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
> &dev_attr_read_latency,
> &dev_attr_write_latency,
> &dev_attr_cmd_latency,
> + &dev_attr_zfcp_access_denied,
> + &dev_attr_zfcp_failed,
> + &dev_attr_zfcp_in_recovery,
> + &dev_attr_zfcp_status,
> NULL
> };
>
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] zfcp: auto port scan resiliency
2014-11-13 13:59 ` [PATCH 3/3] zfcp: auto port scan resiliency Steffen Maier
@ 2014-11-17 13:37 ` Hannes Reinecke
0 siblings, 0 replies; 9+ messages in thread
From: Hannes Reinecke @ 2014-11-17 13:37 UTC (permalink / raw)
To: Steffen Maier, James Bottomley
Cc: linux-scsi, linux-s390, Martin Schwidefsky, Heiko Carstens,
Martin Peschke
On 11/13/2014 02:59 PM, Steffen Maier wrote:
> From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
>
> This patch improves the Fibre Channel port scan behaviour of the zfcp lldd.
> Without it the zfcp device driver may churn up the storage area network by
> excessive scanning and scan bursts, particularly in big virtual server
> environments, potentially resulting in interference of virtual servers and
> reduced availability of storage connectivity.
>
> The two main issues as to the zfcp device drivers automatic port scan in
> virtual server environments are frequency and simultaneity.
> On the one hand, there is no point in allowing lots of ports scans
> in a row. It makes sense, though, to make sure that a scan is conducted
> eventually if there has been any indication for potential SAN changes.
> On the other hand, lots of virtual servers receiving the same indication
> for a SAN change had better not attempt to conduct a scan instantly,
> that is, at the same time.
>
> Hence this patch has a two-fold approach for better port scanning:
> the introduction of a rate limit to amend frequency issues, and the
> introduction of a short random backoff to amend simultaneity issues.
> Both approaches boil down to deferred port scans, with delays
> comprising parts for both approaches.
>
> The new port scan behaviour is summarised best by:
>
> NEW: NEW:
> no_auto_port_rescan random rate flush
> backoff limit =wait
>
> adapter resume/thaw yes yes no yes*
> adapter online (user) no yes no yes*
> port rescan (user) no no no yes
> adapter recovery (user) yes yes yes no
> adapter recovery (other) yes yes yes no
> incoming ELS yes yes yes no
> incoming ELS lost yes yes yes no
>
> Implementation is straight-forward by converting an existing worker to
> a delayed worker. But care is needed whenever that worker is going to be
> flushed (in order to make sure work has been completed), since a flush
> operation cancels the timer set up for deferred execution (see * above).
>
> There is a small race window whenever a port scan work starts
> running up to the point in time of storing the time stamp for that port
> scan. The impact is negligible. Closing that gap isn't trivial, though, and
> would the destroy the beauty of a simple work-to-delayed-work conversion.
>
> Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
> Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
> ---
> drivers/s390/scsi/zfcp_aux.c | 6 +++--
> drivers/s390/scsi/zfcp_ccw.c | 32 ++++++++++++++++++++++----
> drivers/s390/scsi/zfcp_def.h | 3 ++-
> drivers/s390/scsi/zfcp_ext.h | 1 +
> drivers/s390/scsi/zfcp_fc.c | 52 +++++++++++++++++++++++++++++++++++++++---
> drivers/s390/scsi/zfcp_sysfs.c | 10 +++++---
> 6 files changed, 90 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
> index 8004b07..01a7339 100644
> --- a/drivers/s390/scsi/zfcp_aux.c
> +++ b/drivers/s390/scsi/zfcp_aux.c
> @@ -353,9 +353,11 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
> adapter->ccw_device = ccw_device;
>
> INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
> - INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
> + INIT_DELAYED_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
> INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
>
> + adapter->next_port_scan = jiffies;
> +
> if (zfcp_qdio_setup(adapter))
> goto failed;
>
> @@ -420,7 +422,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
> {
> struct ccw_device *cdev = adapter->ccw_device;
>
> - cancel_work_sync(&adapter->scan_work);
> + cancel_delayed_work_sync(&adapter->scan_work);
> cancel_work_sync(&adapter->stat_work);
> cancel_work_sync(&adapter->ns_up_work);
> zfcp_destroy_adapter_work_queue(adapter);
> diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
> index f9879d4..54c7b48 100644
> --- a/drivers/s390/scsi/zfcp_ccw.c
> +++ b/drivers/s390/scsi/zfcp_ccw.c
> @@ -56,8 +56,22 @@ static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
> zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
> zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
> tag);
> +
> + /*
> + * We want to scan ports here, with some random backoff and without
> + * rate limit. Recovery has already scheduled a port scan for us,
> + * but with both random delay and rate limit. Nevertheless we get
> + * what we want here by flushing the scheduled work after sleeping
> + * an equivalent random time.
> + * Let the port scan random delay elapse first. If recovery finishes
> + * up to that point in time, that would be perfect for both recovery
> + * and port scan. If not, i.e. recovery takes ages, there was no
> + * point in waiting a random delay on top of the time consumed by
> + * recovery.
> + */
> + msleep(zfcp_fc_port_scan_backoff());
> zfcp_erp_wait(adapter);
> - flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
> + flush_delayed_work(&adapter->scan_work);
>
> zfcp_ccw_adapter_put(adapter);
>
> @@ -162,11 +176,19 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
> adapter->req_no = 0;
>
> zfcp_ccw_activate(cdev, 0, "ccsonl1");
> - /* scan for remote ports
> - either at the end of any successful adapter recovery
> - or only after the adapter recovery for setting a device online */
> +
> + /*
> + * We want to scan ports here, always, with some random delay and
> + * without rate limit - basically what zfcp_ccw_activate() has
> + * achieved for us. Not quite! That port scan depended on
> + * !no_auto_port_rescan. So let's cover the no_auto_port_rescan
> + * case here to make sure a port scan is done unconditionally.
> + * Since zfcp_ccw_activate() has waited the desired random time,
> + * we can immediately schedule and flush a port scan for the
> + * remaining cases.
> + */
> zfcp_fc_inverse_conditional_port_scan(adapter);
> - flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
> + flush_delayed_work(&adapter->scan_work);
> zfcp_ccw_adapter_put(adapter);
> return 0;
> }
> diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
> index d91173f..b8e853e 100644
> --- a/drivers/s390/scsi/zfcp_def.h
> +++ b/drivers/s390/scsi/zfcp_def.h
> @@ -186,12 +186,13 @@ struct zfcp_adapter {
> struct fc_host_statistics *fc_stats;
> struct fsf_qtcb_bottom_port *stats_reset_data;
> unsigned long stats_reset;
> - struct work_struct scan_work;
> + struct delayed_work scan_work;
> struct work_struct ns_up_work;
> struct service_level service_level;
> struct workqueue_struct *work_queue;
> struct device_dma_parameters dma_parms;
> struct zfcp_fc_events events;
> + unsigned long next_port_scan;
> };
>
> struct zfcp_port {
> diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
> index a9c570a..5b50065 100644
> --- a/drivers/s390/scsi/zfcp_ext.h
> +++ b/drivers/s390/scsi/zfcp_ext.h
> @@ -85,6 +85,7 @@ extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
> extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
> extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
> extern void zfcp_fc_sym_name_update(struct work_struct *);
> +extern unsigned int zfcp_fc_port_scan_backoff(void);
> extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
> extern void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *);
>
> diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
> index ca28e1c..25d49f3 100644
> --- a/drivers/s390/scsi/zfcp_fc.c
> +++ b/drivers/s390/scsi/zfcp_fc.c
> @@ -12,6 +12,7 @@
> #include <linux/types.h>
> #include <linux/slab.h>
> #include <linux/utsname.h>
> +#include <linux/random.h>
> #include <scsi/fc/fc_els.h>
> #include <scsi/libfc.h>
> #include "zfcp_ext.h"
> @@ -31,12 +32,54 @@ module_param_named(no_auto_port_rescan, no_auto_port_rescan, bool, 0600);
> MODULE_PARM_DESC(no_auto_port_rescan,
> "no automatic port_rescan (default off)");
>
> +static unsigned int port_scan_backoff = 500;
> +module_param(port_scan_backoff, uint, 0600);
> +MODULE_PARM_DESC(port_scan_backoff,
> + "upper limit of port scan random backoff in msecs (default 500)");
> +
> +static unsigned int port_scan_ratelimit = 60000;
> +module_param(port_scan_ratelimit, uint, 0600);
> +MODULE_PARM_DESC(port_scan_ratelimit,
> + "minimum interval between port scans in msecs (default 60000)");
> +
> +unsigned int zfcp_fc_port_scan_backoff(void)
> +{
> + if (!port_scan_backoff)
> + return 0;
> + return get_random_int() % port_scan_backoff;
> +}
> +
> +static void zfcp_fc_port_scan_time(struct zfcp_adapter *adapter)
> +{
> + unsigned long interval = msecs_to_jiffies(port_scan_ratelimit);
> + unsigned long backoff = msecs_to_jiffies(zfcp_fc_port_scan_backoff());
> +
> + adapter->next_port_scan = jiffies + interval + backoff;
> +}
> +
> +static void zfcp_fc_port_scan(struct zfcp_adapter *adapter)
> +{
> + unsigned long now = jiffies;
> + unsigned long next = adapter->next_port_scan;
> + unsigned long delay = 0, max;
> +
> + /* delay only needed within waiting period */
> + if (time_before(now, next)) {
> + delay = next - now;
> + /* paranoia: never ever delay scans longer than specified */
> + max = msecs_to_jiffies(port_scan_ratelimit + port_scan_backoff);
> + delay = min(delay, max);
> + }
> +
> + queue_delayed_work(adapter->work_queue, &adapter->scan_work, delay);
> +}
> +
> void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter)
> {
> if (no_auto_port_rescan)
> return;
>
> - queue_work(adapter->work_queue, &adapter->scan_work);
> + zfcp_fc_port_scan(adapter);
> }
>
> void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
> @@ -44,7 +87,7 @@ void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
> if (!no_auto_port_rescan)
> return;
>
> - queue_work(adapter->work_queue, &adapter->scan_work);
> + zfcp_fc_port_scan(adapter);
> }
>
> /**
> @@ -680,12 +723,15 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req,
> */
> void zfcp_fc_scan_ports(struct work_struct *work)
> {
> - struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
> + struct delayed_work *dw = to_delayed_work(work);
> + struct zfcp_adapter *adapter = container_of(dw, struct zfcp_adapter,
> scan_work);
> int ret, i;
> struct zfcp_fc_req *fc_req;
> int chain, max_entries, buf_num, max_bytes;
>
> + zfcp_fc_port_scan_time(adapter);
> +
> chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
> buf_num = chain ? ZFCP_FC_GPN_FT_NUM_BUFS : 1;
> max_entries = chain ? ZFCP_FC_GPN_FT_MAX_ENT : ZFCP_FC_GPN_FT_ENT_PAGE;
> diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
> index a488c09..96a0be1 100644
> --- a/drivers/s390/scsi/zfcp_sysfs.c
> +++ b/drivers/s390/scsi/zfcp_sysfs.c
> @@ -221,9 +221,13 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
> if (!adapter)
> return -ENODEV;
>
> - /* sync the user-space- with the kernel-invocation of scan_work */
> - queue_work(adapter->work_queue, &adapter->scan_work);
> - flush_work(&adapter->scan_work);
> + /*
> + * Users wish is our command: immediately schedule and flush a
> + * worker to conduct a synchronous port scan, that is, neither
> + * a random delay nor a rate limit is applied here.
> + */
> + queue_delayed_work(adapter->work_queue, &adapter->scan_work, 0);
> + flush_delayed_work(&adapter->scan_work);
> zfcp_ccw_adapter_put(adapter);
>
> return (ssize_t) count;
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/3] zfcp features for 3.19
2014-11-13 13:59 [PATCH 0/3] zfcp features for 3.19 Steffen Maier
` (2 preceding siblings ...)
2014-11-13 13:59 ` [PATCH 3/3] zfcp: auto port scan resiliency Steffen Maier
@ 2014-11-20 15:52 ` Christoph Hellwig
3 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2014-11-20 15:52 UTC (permalink / raw)
To: Steffen Maier
Cc: James Bottomley, linux-scsi, linux-s390, Martin Schwidefsky,
Heiko Carstens
Thanks, applied all three patches to drivers-for-3.19
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-11-20 15:52 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-13 13:59 [PATCH 0/3] zfcp features for 3.19 Steffen Maier
2014-11-13 13:59 ` [PATCH 1/3] zfcp: remove access control tables interface (port leftovers) Steffen Maier
2014-11-17 13:29 ` Hannes Reinecke
2014-11-17 13:33 ` Hannes Reinecke
2014-11-13 13:59 ` [PATCH 2/3] zfcp: bring back unit sysfs attributes for automatic LUN scan Steffen Maier
2014-11-17 13:34 ` Hannes Reinecke
2014-11-13 13:59 ` [PATCH 3/3] zfcp: auto port scan resiliency Steffen Maier
2014-11-17 13:37 ` Hannes Reinecke
2014-11-20 15:52 ` [PATCH 0/3] zfcp features for 3.19 Christoph Hellwig
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).