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

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