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

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