multipath-tools/multipath-tools-implement-dev_loss_tmo

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