Blame SOURCES/0099-libmultipath-add-a-protocol-subsection-to-multipath..patch

c90e5b
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
c90e5b
From: Benjamin Marzinski <bmarzins@redhat.com>
c90e5b
Date: Wed, 13 Apr 2022 23:27:37 -0500
c90e5b
Subject: [PATCH] libmultipath: add a protocol subsection to multipath.conf
c90e5b
c90e5b
Some storage arrays can be accessed using multiple protocols at the same
c90e5b
time.  In these cases, users may want to set path attributes
c90e5b
differently, depending on the protocol that the path is using. To allow
c90e5b
this, add a protocol subsection to the overrides section in
c90e5b
multipath.conf, which allows select path-specific options to be set.
c90e5b
This commit simply adds the subsection, and handles merging matching
c90e5b
entries. Future patches will make use of the section.
c90e5b
c90e5b
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
c90e5b
Reviewed-by: Martin Wilck <mwilck@suse.com>
c90e5b
---
c90e5b
 libmultipath/config.c | 83 ++++++++++++++++++++++++++++++++++++
c90e5b
 libmultipath/config.h | 10 +++++
c90e5b
 libmultipath/dict.c   | 99 +++++++++++++++++++++++++++++++++++++++++++
c90e5b
 libmultipath/print.c  | 44 +++++++++++++++++++
c90e5b
 4 files changed, 236 insertions(+)
c90e5b
c90e5b
diff --git a/libmultipath/config.c b/libmultipath/config.c
c90e5b
index aa79561e..88975323 100644
c90e5b
--- a/libmultipath/config.c
c90e5b
+++ b/libmultipath/config.c
c90e5b
@@ -173,6 +173,18 @@ char *get_mpe_wwid(vector mptable, char *alias)
c90e5b
 	return NULL;
c90e5b
 }
c90e5b
 
c90e5b
+static void
c90e5b
+free_pctable (vector pctable)
c90e5b
+{
c90e5b
+	int i;
c90e5b
+	struct pcentry *pce;
c90e5b
+
c90e5b
+	vector_foreach_slot(pctable, pce, i)
c90e5b
+		free(pce);
c90e5b
+
c90e5b
+	vector_free(pctable);
c90e5b
+}
c90e5b
+
c90e5b
 void
c90e5b
 free_hwe (struct hwentry * hwe)
c90e5b
 {
c90e5b
@@ -218,6 +230,9 @@ free_hwe (struct hwentry * hwe)
c90e5b
 	if (hwe->bl_product)
c90e5b
 		FREE(hwe->bl_product);
c90e5b
 
c90e5b
+	if (hwe->pctable)
c90e5b
+		free_pctable(hwe->pctable);
c90e5b
+
c90e5b
 	FREE(hwe);
c90e5b
 }
c90e5b
 
c90e5b
@@ -299,6 +314,15 @@ alloc_hwe (void)
c90e5b
 	return hwe;
c90e5b
 }
c90e5b
 
c90e5b
+struct pcentry *
c90e5b
+alloc_pce (void)
c90e5b
+{
c90e5b
+	struct pcentry *pce = (struct pcentry *)
c90e5b
+				calloc(1, sizeof(struct pcentry));
c90e5b
+	pce->type = -1;
c90e5b
+	return pce;
c90e5b
+}
c90e5b
+
c90e5b
 static char *
c90e5b
 set_param_str(const char * str)
c90e5b
 {
c90e5b
@@ -332,6 +356,13 @@ set_param_str(const char * str)
c90e5b
 	if (!dst->s && src->s) \
c90e5b
 		dst->s = src->s
c90e5b
 
c90e5b
+static void
c90e5b
+merge_pce(struct pcentry *dst, struct pcentry *src)
c90e5b
+{
c90e5b
+	merge_num(fast_io_fail);
c90e5b
+	merge_num(dev_loss);
c90e5b
+	merge_num(eh_deadline);
c90e5b
+}
c90e5b
 
c90e5b
 static void
c90e5b
 merge_hwe (struct hwentry * dst, struct hwentry * src)
c90e5b
@@ -538,6 +569,51 @@ out:
c90e5b
 	return 1;
c90e5b
 }
c90e5b
 
c90e5b
+static void
c90e5b
+validate_pctable(struct hwentry *ovr, int idx, const char *table_desc)
c90e5b
+{
c90e5b
+	struct pcentry *pce;
c90e5b
+
c90e5b
+	if (!ovr || !ovr->pctable)
c90e5b
+		return;
c90e5b
+
c90e5b
+	vector_foreach_slot_after(ovr->pctable, pce, idx) {
c90e5b
+		if (pce->type < 0) {
c90e5b
+			condlog(0, "protocol section in %s missing type",
c90e5b
+				table_desc);
c90e5b
+			vector_del_slot(ovr->pctable, idx--);
c90e5b
+			free(pce);
c90e5b
+		}
c90e5b
+	}
c90e5b
+
c90e5b
+	if (VECTOR_SIZE(ovr->pctable) == 0) {
c90e5b
+		vector_free(ovr->pctable);
c90e5b
+		ovr->pctable = NULL;
c90e5b
+	}
c90e5b
+}
c90e5b
+
c90e5b
+static void
c90e5b
+merge_pctable(struct hwentry *ovr)
c90e5b
+{
c90e5b
+	struct pcentry *pce1, *pce2;
c90e5b
+	int i, j;
c90e5b
+
c90e5b
+	if (!ovr || !ovr->pctable)
c90e5b
+		return;
c90e5b
+
c90e5b
+	vector_foreach_slot(ovr->pctable, pce1, i) {
c90e5b
+		j = i + 1;
c90e5b
+		vector_foreach_slot_after(ovr->pctable, pce2, j) {
c90e5b
+			if (pce1->type != pce2->type)
c90e5b
+				continue;
c90e5b
+			merge_pce(pce2,pce1);
c90e5b
+			vector_del_slot(ovr->pctable, i--);
c90e5b
+			free(pce1);
c90e5b
+			break;
c90e5b
+		}
c90e5b
+	}
c90e5b
+}
c90e5b
+
c90e5b
 static void
c90e5b
 factorize_hwtable (vector hw, int n, const char *table_desc)
c90e5b
 {
c90e5b
@@ -666,6 +742,7 @@ process_config_dir(struct config *conf, char *dir)
c90e5b
 	int i, n;
c90e5b
 	char path[LINE_MAX];
c90e5b
 	int old_hwtable_size;
c90e5b
+	int old_pctable_size = 0;
c90e5b
 
c90e5b
 	if (dir[0] != '/') {
c90e5b
 		condlog(1, "config_dir '%s' must be a fully qualified path",
c90e5b
@@ -692,11 +769,15 @@ process_config_dir(struct config *conf, char *dir)
c90e5b
 			continue;
c90e5b
 
c90e5b
 		old_hwtable_size = VECTOR_SIZE(conf->hwtable);
c90e5b
+		old_pctable_size = conf->overrides ?
c90e5b
+				   VECTOR_SIZE(conf->overrides->pctable) : 0;
c90e5b
 		snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
c90e5b
 		path[LINE_MAX-1] = '\0';
c90e5b
 		process_file(conf, path);
c90e5b
 		factorize_hwtable(conf->hwtable, old_hwtable_size,
c90e5b
 				  namelist[i]->d_name);
c90e5b
+		validate_pctable(conf->overrides, old_pctable_size,
c90e5b
+				 namelist[i]->d_name);
c90e5b
 	}
c90e5b
 	pthread_cleanup_pop(1);
c90e5b
 }
c90e5b
@@ -784,6 +865,7 @@ load_config (char * file)
c90e5b
 			goto out;
c90e5b
 		}
c90e5b
 		factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
c90e5b
+		validate_pctable(conf->overrides, 0, file);
c90e5b
 	} else {
c90e5b
 		condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
c90e5b
 		condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
c90e5b
@@ -898,6 +980,7 @@ load_config (char * file)
c90e5b
 			goto out;
c90e5b
 	}
c90e5b
 
c90e5b
+	merge_pctable(conf->overrides);
c90e5b
 	merge_mptable(conf->mptable);
c90e5b
 	merge_blacklist(conf->blist_devnode);
c90e5b
 	merge_blacklist(conf->blist_property);
c90e5b
diff --git a/libmultipath/config.h b/libmultipath/config.h
c90e5b
index e2e3f143..143116b3 100644
c90e5b
--- a/libmultipath/config.h
c90e5b
+++ b/libmultipath/config.h
c90e5b
@@ -41,6 +41,13 @@ enum force_reload_types {
c90e5b
 	FORCE_RELOAD_WEAK,
c90e5b
 };
c90e5b
 
c90e5b
+struct pcentry {
c90e5b
+	int type;
c90e5b
+	int fast_io_fail;
c90e5b
+	unsigned int dev_loss;
c90e5b
+	int eh_deadline;
c90e5b
+};
c90e5b
+
c90e5b
 struct hwentry {
c90e5b
 	char * vendor;
c90e5b
 	char * product;
c90e5b
@@ -86,6 +93,8 @@ struct hwentry {
c90e5b
 	int vpd_vendor_id;
c90e5b
 	int recheck_wwid;
c90e5b
 	char * bl_product;
c90e5b
+
c90e5b
+	vector pctable;
c90e5b
 };
c90e5b
 
c90e5b
 struct mpentry {
c90e5b
@@ -240,6 +249,7 @@ char * get_mpe_wwid (vector mptable, char * alias);
c90e5b
 
c90e5b
 struct hwentry * alloc_hwe (void);
c90e5b
 struct mpentry * alloc_mpe (void);
c90e5b
+struct pcentry * alloc_pce (void);
c90e5b
 
c90e5b
 void free_hwe (struct hwentry * hwe);
c90e5b
 void free_hwtable (vector hwtable);
c90e5b
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
c90e5b
index 5a0255b0..8321ec1e 100644
c90e5b
--- a/libmultipath/dict.c
c90e5b
+++ b/libmultipath/dict.c
c90e5b
@@ -457,6 +457,29 @@ snprint_mp_ ## option (struct config *conf, char * buff, int len,	\
c90e5b
 	return function (buff, len, mpe->option);			\
c90e5b
 }
c90e5b
 
c90e5b
+#define declare_pc_handler(option, function)				\
c90e5b
+static int								\
c90e5b
+pc_ ## option ## _handler (struct config *conf, vector strvec,		\
c90e5b
+			   const char *file, int line_nr)		\
c90e5b
+{									\
c90e5b
+	struct pcentry *pce;						\
c90e5b
+	if (!conf->overrides || !conf->overrides->pctable)		\
c90e5b
+		return 1;						\
c90e5b
+	pce = VECTOR_LAST_SLOT(conf->overrides->pctable);		\
c90e5b
+	if (!pce)							\
c90e5b
+		return 1;						\
c90e5b
+	return function (strvec, &pce->option, file, line_nr);		\
c90e5b
+}
c90e5b
+
c90e5b
+#define declare_pc_snprint(option, function)				\
c90e5b
+static int								\
c90e5b
+snprint_pc_ ## option (struct config *conf, char * buff, int len,	\
c90e5b
+		       const void *data)				\
c90e5b
+{									\
c90e5b
+	const struct pcentry *pce  = (const struct pcentry *)data;	\
c90e5b
+	return function(buff, len, pce->option);			\
c90e5b
+}
c90e5b
+
c90e5b
 static int checkint_handler(struct config *conf, vector strvec,
c90e5b
 			    const char *file, int line_nr)
c90e5b
 {
c90e5b
@@ -1022,6 +1045,8 @@ declare_ovr_handler(fast_io_fail, set_undef_off_zero)
c90e5b
 declare_ovr_snprint(fast_io_fail, print_undef_off_zero)
c90e5b
 declare_hw_handler(fast_io_fail, set_undef_off_zero)
c90e5b
 declare_hw_snprint(fast_io_fail, print_undef_off_zero)
c90e5b
+declare_pc_handler(fast_io_fail, set_undef_off_zero)
c90e5b
+declare_pc_snprint(fast_io_fail, print_undef_off_zero)
c90e5b
 
c90e5b
 static int
c90e5b
 set_dev_loss(vector strvec, void *ptr, const char *file, int line_nr)
c90e5b
@@ -1059,6 +1084,8 @@ declare_ovr_handler(dev_loss, set_dev_loss)
c90e5b
 declare_ovr_snprint(dev_loss, print_dev_loss)
c90e5b
 declare_hw_handler(dev_loss, set_dev_loss)
c90e5b
 declare_hw_snprint(dev_loss, print_dev_loss)
c90e5b
+declare_pc_handler(dev_loss, set_dev_loss)
c90e5b
+declare_pc_snprint(dev_loss, print_dev_loss)
c90e5b
 
c90e5b
 declare_def_handler(eh_deadline, set_undef_off_zero)
c90e5b
 declare_def_snprint(eh_deadline, print_undef_off_zero)
c90e5b
@@ -1066,6 +1093,8 @@ declare_ovr_handler(eh_deadline, set_undef_off_zero)
c90e5b
 declare_ovr_snprint(eh_deadline, print_undef_off_zero)
c90e5b
 declare_hw_handler(eh_deadline, set_undef_off_zero)
c90e5b
 declare_hw_snprint(eh_deadline, print_undef_off_zero)
c90e5b
+declare_pc_handler(eh_deadline, set_undef_off_zero)
c90e5b
+declare_pc_snprint(eh_deadline, print_undef_off_zero)
c90e5b
 
c90e5b
 static int
c90e5b
 set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
c90e5b
@@ -1876,6 +1905,69 @@ declare_mp_snprint(wwid, print_str)
c90e5b
 declare_mp_handler(alias, set_str_noslash)
c90e5b
 declare_mp_snprint(alias, print_str)
c90e5b
 
c90e5b
+
c90e5b
+static int
c90e5b
+protocol_handler(struct config *conf, vector strvec, const char *file,
c90e5b
+               int line_nr)
c90e5b
+{
c90e5b
+	struct pcentry *pce;
c90e5b
+
c90e5b
+	if (!conf->overrides)
c90e5b
+		return 1;
c90e5b
+
c90e5b
+	if (!conf->overrides->pctable &&
c90e5b
+	    !(conf->overrides->pctable = vector_alloc()))
c90e5b
+		return 1;
c90e5b
+
c90e5b
+	if (!(pce = alloc_pce()))
c90e5b
+		return 1;
c90e5b
+
c90e5b
+	if (!vector_alloc_slot(conf->overrides->pctable)) {
c90e5b
+		free(pce);
c90e5b
+		return 1;
c90e5b
+	}
c90e5b
+	vector_set_slot(conf->overrides->pctable, pce);
c90e5b
+
c90e5b
+	return 0;
c90e5b
+}
c90e5b
+
c90e5b
+static int
c90e5b
+set_protocol_type(vector strvec, void *ptr, const char *file, int line_nr)
c90e5b
+{
c90e5b
+	int *int_ptr = (int *)ptr;
c90e5b
+	char *buff;
c90e5b
+	int i;
c90e5b
+
c90e5b
+	buff = set_value(strvec);
c90e5b
+
c90e5b
+	if (!buff)
c90e5b
+		return 1;
c90e5b
+
c90e5b
+	for (i = 0; i <= LAST_BUS_PROTOCOL_ID; i++) {
c90e5b
+		if (protocol_name[i] && !strcmp(buff, protocol_name[i])) {
c90e5b
+			*int_ptr = i;
c90e5b
+			break;
c90e5b
+		}
c90e5b
+	}
c90e5b
+	if (i > LAST_BUS_PROTOCOL_ID)
c90e5b
+		condlog(1, "%s line %d, invalid value for type: \"%s\"",
c90e5b
+			file, line_nr, buff);
c90e5b
+
c90e5b
+	free(buff);
c90e5b
+	return 0;
c90e5b
+}
c90e5b
+
c90e5b
+static int
c90e5b
+print_protocol_type(char *buff, int len, int type)
c90e5b
+{
c90e5b
+	if (type < 0)
c90e5b
+		return 0;
c90e5b
+	return snprintf(buff, len, "\"%s\"", protocol_name[type]);
c90e5b
+}
c90e5b
+
c90e5b
+declare_pc_handler(type, set_protocol_type)
c90e5b
+declare_pc_snprint(type, print_protocol_type)
c90e5b
+
c90e5b
 /*
c90e5b
  * deprecated handlers
c90e5b
  */
c90e5b
@@ -2117,6 +2209,13 @@ init_keywords(vector keywords)
c90e5b
 	install_keyword("ghost_delay", &ovr_ghost_delay_handler, &snprint_ovr_ghost_delay);
c90e5b
 	install_keyword("all_tg_pt", &ovr_all_tg_pt_handler, &snprint_ovr_all_tg_pt);
c90e5b
 	install_keyword("recheck_wwid", &ovr_recheck_wwid_handler, &snprint_ovr_recheck_wwid);
c90e5b
+	install_keyword_multi("protocol", &protocol_handler, NULL);
c90e5b
+	install_sublevel();
c90e5b
+	install_keyword("type", &pc_type_handler, &snprint_pc_type);
c90e5b
+	install_keyword("fast_io_fail_tmo", &pc_fast_io_fail_handler, &snprint_pc_fast_io_fail);
c90e5b
+	install_keyword("dev_loss_tmo", &pc_dev_loss_handler, &snprint_pc_dev_loss);
c90e5b
+	install_keyword("eh_deadline", &pc_eh_deadline_handler, &snprint_pc_eh_deadline);
c90e5b
+	install_sublevel_end();
c90e5b
 
c90e5b
 	install_keyword_root("multipaths", &multipaths_handler);
c90e5b
 	install_keyword_multi("multipath", &multipath_handler, NULL);
c90e5b
diff --git a/libmultipath/print.c b/libmultipath/print.c
c90e5b
index 1f6d27bd..8a6fbe83 100644
c90e5b
--- a/libmultipath/print.c
c90e5b
+++ b/libmultipath/print.c
c90e5b
@@ -1392,6 +1392,39 @@ snprint_multipath_topology_json (char * buff, int len, const struct vectors * ve
c90e5b
 	return fwd;
c90e5b
 }
c90e5b
 
c90e5b
+static int
c90e5b
+snprint_pcentry (const struct config *conf, char *buff, int len,
c90e5b
+		 const struct pcentry *pce)
c90e5b
+{
c90e5b
+	int i;
c90e5b
+	int fwd = 0;
c90e5b
+	struct keyword *kw;
c90e5b
+	struct keyword *rootkw;
c90e5b
+
c90e5b
+	rootkw = find_keyword(conf->keywords, NULL, "overrides");
c90e5b
+	if (!rootkw || !rootkw->sub)
c90e5b
+		return 0;
c90e5b
+
c90e5b
+	rootkw = find_keyword(conf->keywords, rootkw->sub, "protocol");
c90e5b
+	if (!rootkw)
c90e5b
+		return 0;
c90e5b
+
c90e5b
+	fwd += snprintf(buff + fwd, len - fwd, "\tprotocol {\n");
c90e5b
+	if (fwd >= len)
c90e5b
+		return len;
c90e5b
+
c90e5b
+	iterate_sub_keywords(rootkw, kw, i) {
c90e5b
+		fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n",
c90e5b
+				kw, pce);
c90e5b
+		if (fwd >= len)
c90e5b
+			return len;
c90e5b
+	}
c90e5b
+	fwd += snprintf(buff + fwd, len - fwd, "\t}\n");
c90e5b
+	if (fwd >= len)
c90e5b
+		return len;
c90e5b
+	return fwd;
c90e5b
+}
c90e5b
+
c90e5b
 static int
c90e5b
 snprint_hwentry (const struct config *conf,
c90e5b
 		 char * buff, int len, const struct hwentry * hwe)
c90e5b
@@ -1575,6 +1608,17 @@ static int snprint_overrides(const struct config *conf, char * buff, int len,
c90e5b
 		if (fwd >= len)
c90e5b
 			return len;
c90e5b
 	}
c90e5b
+
c90e5b
+	if (overrides->pctable) {
c90e5b
+		struct pcentry *pce;
c90e5b
+
c90e5b
+		vector_foreach_slot(overrides->pctable, pce, i) {
c90e5b
+			fwd += snprint_pcentry(conf, buff + fwd, len - fwd,
c90e5b
+					       pce);
c90e5b
+			if (fwd >= len)
c90e5b
+				return len;
c90e5b
+		}
c90e5b
+	}
c90e5b
 out:
c90e5b
 	fwd += snprintf(buff + fwd, len - fwd, "}\n");
c90e5b
 	if (fwd >= len)