424 lines
11 KiB
Plaintext
424 lines
11 KiB
Plaintext
From 4c6e3b7eff9825353610bfc3130276e6f5233247 Mon Sep 17 00:00:00 2001
|
|
From: Hannes Reinecke <hare@suse.de>
|
|
Date: Tue, 13 Jan 2009 16:01:30 +0100
|
|
Subject: [PATCH] Implement dev_loss_tmo and fast_io_fail_tmo
|
|
|
|
When using multipath the 'dev_loss_tmo' and 'fast_io_fail_tmo'
|
|
settings should be as small as possible to avoid any stalls
|
|
in multipathd. So we should be able to configure both
|
|
from within mulitpath.
|
|
|
|
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
|
---
|
|
libmultipath/config.c | 2 +
|
|
libmultipath/config.h | 4 +
|
|
libmultipath/dict.c | 144 ++++++++++++++++++++++++++++++++++++++++++++
|
|
libmultipath/discovery.c | 104 +++++++++++++++++++++++++++++++
|
|
libmultipath/discovery.h | 1 +
|
|
libmultipath/structs_vec.c | 6 ++
|
|
multipath/multipath.conf.5 | 12 ++++
|
|
7 files changed, 273 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
|
index 83da6e7..ea7ad99 100644
|
|
--- a/libmultipath/config.c
|
|
+++ b/libmultipath/config.c
|
|
@@ -463,6 +463,8 @@ load_config (char * file)
|
|
conf->dev_type = DEV_NONE;
|
|
conf->minio = 1000;
|
|
conf->max_fds = 0;
|
|
+ conf->dev_loss_tmo = 0;
|
|
+ conf->fast_io_fail_tmo = 0;
|
|
conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
|
|
|
|
/*
|
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
|
index fc0e22d..7d23927 100644
|
|
--- a/libmultipath/config.h
|
|
+++ b/libmultipath/config.h
|
|
@@ -29,6 +29,8 @@ struct hwentry {
|
|
int no_path_retry;
|
|
int minio;
|
|
int pg_timeout;
|
|
+ int dev_loss_tmo;
|
|
+ int fast_io_fail_tmo;
|
|
char * bl_product;
|
|
};
|
|
|
|
@@ -67,6 +69,8 @@ struct config {
|
|
int pg_timeout;
|
|
int max_fds;
|
|
int force_reload;
|
|
+ int dev_loss_tmo;
|
|
+ int fast_io_fail_tmo;
|
|
|
|
char * dev;
|
|
char * sysfs_dir;
|
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
|
index 09ecf51..ed77000 100644
|
|
--- a/libmultipath/dict.c
|
|
+++ b/libmultipath/dict.c
|
|
@@ -189,6 +189,46 @@ max_fds_handler(vector strvec)
|
|
}
|
|
|
|
static int
|
|
+def_dev_loss_tmo_handler(vector strvec)
|
|
+{
|
|
+ char * buff;
|
|
+
|
|
+ buff = set_value(strvec);
|
|
+
|
|
+ if (!buff)
|
|
+ return 1;
|
|
+
|
|
+ if (strlen(buff) == 9 &&
|
|
+ !strcmp(buff, "off"))
|
|
+ conf->dev_loss_tmo = -1;
|
|
+ else
|
|
+ conf->dev_loss_tmo = atoi(buff);
|
|
+ FREE(buff);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+def_fast_io_fail_tmo_handler(vector strvec)
|
|
+{
|
|
+ char * buff;
|
|
+
|
|
+ buff = set_value(strvec);
|
|
+
|
|
+ if (!buff)
|
|
+ return 1;
|
|
+
|
|
+ if (strlen(buff) == 9 &&
|
|
+ !strcmp(buff, "off"))
|
|
+ conf->fast_io_fail_tmo = -1;
|
|
+ else
|
|
+ conf->fast_io_fail_tmo = atoi(buff);
|
|
+ FREE(buff);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
def_weight_handler(vector strvec)
|
|
{
|
|
char * buff;
|
|
@@ -779,6 +819,54 @@ hw_pg_timeout_handler(vector strvec)
|
|
return 0;
|
|
}
|
|
|
|
+static int
|
|
+hw_dev_loss_tmo_handler(vector strvec)
|
|
+{
|
|
+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
|
|
+ char * buff;
|
|
+
|
|
+ if (!hwe)
|
|
+ return 1;
|
|
+
|
|
+ buff = set_value(strvec);
|
|
+
|
|
+ if (!buff)
|
|
+ return 1;
|
|
+
|
|
+ if (strlen(buff) == 9 &&
|
|
+ !strcmp(buff, "off"))
|
|
+ hwe->dev_loss_tmo = -1;
|
|
+ else
|
|
+ hwe->dev_loss_tmo = atoi(buff);
|
|
+ FREE(buff);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+hw_fast_io_fail_tmo_handler(vector strvec)
|
|
+{
|
|
+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
|
|
+ char * buff;
|
|
+
|
|
+ if (!hwe)
|
|
+ return 1;
|
|
+
|
|
+ buff = set_value(strvec);
|
|
+
|
|
+ if (!buff)
|
|
+ return 1;
|
|
+
|
|
+ if (strlen(buff) == 9 &&
|
|
+ !strcmp(buff, "off"))
|
|
+ hwe->fast_io_fail_tmo = -1;
|
|
+ else
|
|
+ hwe->fast_io_fail_tmo = atoi(buff);
|
|
+ FREE(buff);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* multipaths block handlers
|
|
*/
|
|
@@ -1406,6 +1494,36 @@ snprint_hw_path_checker (char * buff, int len, void * data)
|
|
}
|
|
|
|
static int
|
|
+snprint_hw_dev_loss_tmo (char * buff, int len, void * data)
|
|
+{
|
|
+ struct hwentry * hwe = (struct hwentry *)data;
|
|
+
|
|
+ if (!hwe->dev_loss_tmo)
|
|
+ return 0;
|
|
+ if (hwe->dev_loss_tmo == conf->dev_loss_tmo)
|
|
+ return 0;
|
|
+
|
|
+ if (hwe->dev_loss_tmo < 0)
|
|
+ return snprintf(buff, len, "off");
|
|
+ return snprintf(buff, len, "%u", hwe->dev_loss_tmo);
|
|
+}
|
|
+
|
|
+static int
|
|
+snprint_hw_fast_io_fail_tmo (char * buff, int len, void * data)
|
|
+{
|
|
+ struct hwentry * hwe = (struct hwentry *)data;
|
|
+
|
|
+ if (!hwe->fast_io_fail_tmo)
|
|
+ return 0;
|
|
+ if (hwe->fast_io_fail_tmo == conf->fast_io_fail_tmo)
|
|
+ return 0;
|
|
+
|
|
+ if (hwe->fast_io_fail_tmo < 0)
|
|
+ return snprintf(buff, len, "off");
|
|
+ return snprintf(buff, len, "%u", hwe->fast_io_fail_tmo);
|
|
+}
|
|
+
|
|
+static int
|
|
snprint_def_polling_interval (char * buff, int len, void * data)
|
|
{
|
|
if (conf->checkint == DEFAULT_CHECKINT)
|
|
@@ -1565,6 +1683,28 @@ snprint_max_fds (char * buff, int len, void * data)
|
|
}
|
|
|
|
static int
|
|
+snprint_def_dev_loss_tmo (char * buff, int len, void * data)
|
|
+{
|
|
+ if (!conf->dev_loss_tmo)
|
|
+ return 0;
|
|
+
|
|
+ if (conf->dev_loss_tmo < 0)
|
|
+ return snprintf(buff, len, "off");
|
|
+ return snprintf(buff, len, "%d", conf->dev_loss_tmo);
|
|
+}
|
|
+
|
|
+static int
|
|
+snprint_def_fast_io_fail_tmo (char * buff, int len, void * data)
|
|
+{
|
|
+ if (!conf->fast_io_fail_tmo)
|
|
+ return 0;
|
|
+
|
|
+ if (conf->fast_io_fail_tmo < 0)
|
|
+ return snprintf(buff, len, "off");
|
|
+ return snprintf(buff, len, "%d", conf->fast_io_fail_tmo);
|
|
+}
|
|
+
|
|
+static int
|
|
snprint_def_rr_weight (char * buff, int len, void * data)
|
|
{
|
|
if (!conf->rr_weight)
|
|
@@ -1681,6 +1821,8 @@ init_keywords(void)
|
|
install_keyword("failback", &default_failback_handler, &snprint_def_failback);
|
|
install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io);
|
|
install_keyword("max_fds", &max_fds_handler, &snprint_max_fds);
|
|
+ install_keyword("dev_loss_tmo", &def_dev_loss_tmo_handler, &snprint_def_dev_loss_tmo);
|
|
+ install_keyword("fast_io_fail_tmo", &def_fast_io_fail_tmo_handler, &snprint_def_fast_io_fail_tmo);
|
|
install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight);
|
|
install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry);
|
|
install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout);
|
|
@@ -1739,6 +1881,8 @@ init_keywords(void)
|
|
install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry);
|
|
install_keyword("rr_min_io", &hw_minio_handler, &snprint_hw_rr_min_io);
|
|
install_keyword("pg_timeout", &hw_pg_timeout_handler, &snprint_hw_pg_timeout);
|
|
+ install_keyword("dev_loss_tmo", &hw_dev_loss_tmo_handler, &snprint_hw_dev_loss_tmo);
|
|
+ install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_tmo_handler, &snprint_hw_fast_io_fail_tmo);
|
|
install_sublevel_end();
|
|
|
|
install_keyword_root("multipaths", &multipaths_handler);
|
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
|
index afd247d..6e4ce1e 100644
|
|
--- a/libmultipath/discovery.c
|
|
+++ b/libmultipath/discovery.c
|
|
@@ -209,6 +209,110 @@ sysfs_get_fc_nodename (struct sysfs_device * dev, char * node,
|
|
return 1;
|
|
}
|
|
|
|
+int
|
|
+sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo)
|
|
+{
|
|
+ char attr_path[SYSFS_PATH_SIZE];
|
|
+ char host_path[SYSFS_PATH_SIZE];
|
|
+ char attr_value[NAME_SIZE];
|
|
+ DIR *host_dir, *rport_dir;
|
|
+ struct dirent *host_ent, *rport_ent;
|
|
+ int host, channel, lun, port, num;
|
|
+ int rport_channel = -1;
|
|
+ int rport_id = -1;
|
|
+
|
|
+ if (dev_loss_tmo == 0 || fast_io_fail_tmo == 0) {
|
|
+ condlog(4, "%s: no FC settings", pp->dev);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (safe_sprintf(host_path, "/sys/class/fc_host/host%i/device",
|
|
+ pp->sg_id.host_no)) {
|
|
+ condlog(0, "host_path too small");
|
|
+ return 1;
|
|
+ }
|
|
+ if (!(host_dir = opendir(host_path))) {
|
|
+ condlog(3, "host %d not a FC HBA", pp->sg_id.host_no);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ while (rport_channel < 0 && rport_id < 0 &&
|
|
+ (host_ent = readdir(host_dir))) {
|
|
+ if (sscanf(host_ent->d_name, "rport-%d:%d-%d",
|
|
+ &host, &port, &num) != 3)
|
|
+ continue;
|
|
+
|
|
+ if (host != pp->sg_id.host_no)
|
|
+ continue;
|
|
+
|
|
+ if (safe_sprintf(attr_path, "%s/%s",
|
|
+ host_path, host_ent->d_name)) {
|
|
+ condlog(0, "target_path too small");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (!(rport_dir = opendir(attr_path))) {
|
|
+ condlog(1, "cannot open rport path '%s'", attr_path);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ while ((rport_ent = readdir(rport_dir))) {
|
|
+ if (sscanf(rport_ent->d_name, "target%d:%d:%d",
|
|
+ &host, &channel, &lun) != 3)
|
|
+ continue;
|
|
+
|
|
+ if (host != pp->sg_id.host_no &&
|
|
+ channel != pp->sg_id.channel &&
|
|
+ lun != pp->sg_id.scsi_id)
|
|
+ continue;
|
|
+
|
|
+ rport_channel = port;
|
|
+ rport_id = num;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (rport_channel < 0 && rport_id < 0) {
|
|
+ condlog(1, "No rport found");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (safe_sprintf(attr_path,
|
|
+ "/class/fc_remote_ports/rport-%d:%d-%d",
|
|
+ pp->sg_id.host_no, rport_channel, rport_id)) {
|
|
+ condlog(0, "attr_path too small");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (dev_loss_tmo < 0)
|
|
+ sprintf(attr_value, "%d", 0);
|
|
+ else
|
|
+ sprintf(attr_value, "%d", dev_loss_tmo);
|
|
+ num = sysfs_attr_set_value(attr_path, "dev_loss_tmo",
|
|
+ attr_value, strlen(attr_value));
|
|
+ if (num > 0)
|
|
+ condlog(4, "%s: set dev_loss_tmo to %d", pp->dev,
|
|
+ dev_loss_tmo);
|
|
+ else
|
|
+ condlog(4, "%s: failed to set dev_loss_tmo (%d)",
|
|
+ pp->dev, errno);
|
|
+
|
|
+ if (fast_io_fail_tmo < 0)
|
|
+ sprintf(attr_value, "%d", 0);
|
|
+ else
|
|
+ sprintf(attr_value, "%d", fast_io_fail_tmo);
|
|
+ num = sysfs_attr_set_value(attr_path, "fast_io_fail_tmo",
|
|
+ attr_value, strlen(attr_value));
|
|
+ if (num > 0)
|
|
+ condlog(4, "%s: set fast_io_fail_tmo to %d", pp->dev,
|
|
+ fast_io_fail_tmo);
|
|
+ else
|
|
+ condlog(4, "%s: failed to set fast_io_fail_tmo (%d)",
|
|
+ pp->dev, errno);
|
|
+
|
|
+ return num == strlen(attr_value) ? 0 : 1;
|
|
+}
|
|
+
|
|
static int
|
|
opennode (char * dev, int mode)
|
|
{
|
|
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
|
index 05b1cfe..3749674 100644
|
|
--- a/libmultipath/discovery.h
|
|
+++ b/libmultipath/discovery.h
|
|
@@ -32,6 +32,7 @@ int devt2devname (char *, char *);
|
|
int pathinfo (struct path *, vector hwtable, int mask);
|
|
struct path * store_pathinfo (vector pathvec, vector hwtable,
|
|
char * devname, int flag);
|
|
+int sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo);
|
|
|
|
/*
|
|
* discovery bitmask
|
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
|
index a1d9632..1632c9d 100644
|
|
--- a/libmultipath/structs_vec.c
|
|
+++ b/libmultipath/structs_vec.c
|
|
@@ -479,6 +479,12 @@ verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec)
|
|
free_path(pp);
|
|
}
|
|
} else {
|
|
+ if (pp->hwe)
|
|
+ sysfs_set_fc_values(pp, pp->hwe->dev_loss_tmo,
|
|
+ pp->hwe->fast_io_fail_tmo);
|
|
+ else
|
|
+ sysfs_set_fc_values(pp, conf->dev_loss_tmo,
|
|
+ conf->fast_io_fail_tmo);
|
|
condlog(4, "%s: verified path %s dev_t %s",
|
|
mpp->alias, pp->dev, pp->dev_t);
|
|
}
|
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
|
index 8ac1f1c..926ff69 100644
|
|
--- a/multipath/multipath.conf.5
|
|
+++ b/multipath/multipath.conf.5
|
|
@@ -263,6 +263,14 @@ Default is
|
|
.B bindings_file
|
|
The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to
|
|
.I /var/lib/multipath/bindings
|
|
+.TP
|
|
+.B dev_loss_tmo
|
|
+The default dev_loss_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all devices on that port will be removed from sysfs after this timeout.
|
|
+.TP
|
|
+.B fast_io_fail_tmo
|
|
+The default fast_io_fail_tmo setting for an FC remote port in seconds. If an rport has vanished from the fabric all I/O to the devices on that port will be terminated after this timeout. Should be smaller than
|
|
+.B dev_loss_tmo
|
|
+setting.
|
|
.
|
|
.SH "blacklist section"
|
|
The
|
|
@@ -413,6 +421,10 @@ section:
|
|
.B no_path_retry
|
|
.TP
|
|
.B rr_min_io
|
|
+.TP
|
|
+.B dev_loss_tmo
|
|
+.TP
|
|
+.B fast_io_fail_tmo
|
|
.RE
|
|
.PD
|
|
.LP
|
|
--
|
|
1.5.3.2
|
|
|