[dm-devel] [PATCH] multipath: add support for retain_attached_hw_handler feature

Benjamin Marzinski bmarzins at redhat.com
Tue Jan 8 05:39:21 UTC 2013


This adds support for the retain_attached_hw_handler feature. When this is set to
"yes", if the kernel has already attached a hardware handler to the multipath
path devices, multipath will use that one, instead of its configured one. If
no hardware handler is already attached, multipath use its configured one, if
any.  To properly ignore this on older kernels, I had to makes some changes
to the version checking code.

Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
---
 libmultipath/config.c    |    5 ++-
 libmultipath/config.h    |    4 +-
 libmultipath/configure.c |    7 +++-
 libmultipath/defaults.h  |    1 
 libmultipath/devmapper.c |   34 +++------------------
 libmultipath/devmapper.h |    8 ++++-
 libmultipath/dict.c      |   74 +++++++++++++++++++++++++++++++++++++++++++++++
 libmultipath/dmparser.c  |    3 +
 libmultipath/propsel.c   |   29 +++++++++++++++++-
 libmultipath/propsel.h   |    1 
 libmultipath/structs.h   |    7 ++++
 11 files changed, 138 insertions(+), 35 deletions(-)

Index: multipath-tools-120821/libmultipath/config.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/config.c
+++ multipath-tools-120821/libmultipath/config.c
@@ -326,6 +326,7 @@ merge_hwe (struct hwentry * dst, struct
 	merge_num(fast_io_fail);
 	merge_num(dev_loss);
 	merge_num(user_friendly_names);
+	merge_num(retain_hwhandler);
 
 	return 0;
 }
@@ -385,6 +386,7 @@ store_hwe (vector hwtable, struct hwentr
 	hwe->fast_io_fail = dhwe->fast_io_fail;
 	hwe->dev_loss = dhwe->dev_loss;
 	hwe->user_friendly_names = dhwe->user_friendly_names;
+	hwe->retain_hwhandler = dhwe->retain_hwhandler;
 
 	if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
 		goto out;
@@ -501,7 +503,7 @@ load_config (char * file)
 		conf->verbosity = DEFAULT_VERBOSITY;
 
 	conf->udev = udev_new();
-	conf->dmrq = dm_drv_get_rq();
+	dm_drv_version(conf->version, TGT_MPATH);
 	conf->dev_type = DEV_NONE;
 	conf->minio = DEFAULT_MINIO;
 	conf->minio_rq = DEFAULT_MINIO_RQ;
@@ -517,6 +519,7 @@ load_config (char * file)
 	conf->checkint = DEFAULT_CHECKINT;
 	conf->max_checkint = MAX_CHECKINT(conf->checkint);
 	conf->fast_io_fail = 5;
+	conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
 
 	/*
 	 * preload default hwtable
Index: multipath-tools-120821/libmultipath/config.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/config.h
+++ multipath-tools-120821/libmultipath/config.h
@@ -45,6 +45,7 @@ struct hwentry {
 	int fast_io_fail;
 	unsigned int dev_loss;
 	int user_friendly_names;
+	int retain_hwhandler;
 	char * bl_product;
 };
 
@@ -74,7 +75,6 @@ struct mpentry {
 };
 
 struct config {
-	int dmrq;
 	int verbosity;
 	int dry_run;
 	int list;
@@ -108,6 +108,8 @@ struct config {
 	mode_t mode;
 	uint32_t cookie;
 	int reassign_maps;
+	int retain_hwhandler;
+	unsigned int version[3];
 
 	char * dev;
 	struct udev * udev;
Index: multipath-tools-120821/libmultipath/defaults.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/defaults.h
+++ multipath-tools-120821/libmultipath/defaults.h
@@ -15,6 +15,7 @@
 #define DEFAULT_USER_FRIENDLY_NAMES    0
 #define DEFAULT_VERBOSITY	2
 #define DEFAULT_REASSIGN_MAPS	1
+#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
 
 #define DEFAULT_CHECKINT	5
 #define MAX_CHECKINT(a)		(a << 2)
Index: multipath-tools-120821/libmultipath/dict.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/dict.c
+++ multipath-tools-120821/libmultipath/dict.c
@@ -629,6 +629,29 @@ wwids_file_handler(vector strvec)
 	return 0;
 }
 
+static int
+def_retain_hwhandler_handler(vector strvec)
+{
+	char * buff;
+
+	buff = set_value(strvec);
+
+	if (!buff)
+		return 1;
+
+	if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
+	    (strlen(buff) == 1 && !strcmp(buff, "0")))
+		conf->retain_hwhandler = RETAIN_HWHANDLER_OFF;
+	else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+		 (strlen(buff) == 1 && !strcmp(buff, "1")))
+		conf->retain_hwhandler = RETAIN_HWHANDLER_ON;
+	else
+		conf->retain_hwhandler = RETAIN_HWHANDLER_UNDEF;
+
+	FREE(buff);
+	return 0;
+}
+
 /*
  * blacklist block handlers
  */
@@ -1250,6 +1273,33 @@ hw_names_handler(vector strvec)
 	return 0;
 }
 
+static int
+hw_retain_hwhandler_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) == 2 && !strcmp(buff, "no")) ||
+	    (strlen(buff) == 1 && !strcmp(buff, "0")))
+		hwe->retain_hwhandler = RETAIN_HWHANDLER_OFF;
+	else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+		 (strlen(buff) == 1 && !strcmp(buff, "1")))
+		hwe->retain_hwhandler = RETAIN_HWHANDLER_ON;
+	else
+		hwe->user_friendly_names = RETAIN_HWHANDLER_UNDEF;
+
+	FREE(buff);
+	return 0;
+}
+
 /*
  * multipaths block handlers
  */
@@ -2274,6 +2324,19 @@ snprint_hw_user_friendly_names (char * b
 }
 
 static int
+snprint_hw_retain_hwhandler_handler(char * buff, int len, void * data)
+{
+	struct hwentry * hwe = (struct hwentry *)data;
+
+	if (hwe->retain_hwhandler == RETAIN_HWHANDLER_ON)
+		return snprintf(buff, len, "yes");
+	else if (hwe->retain_hwhandler == RETAIN_HWHANDLER_OFF)
+		return snprintf(buff, len, "no");
+	else
+		return 0;
+}
+
+static int
 snprint_def_polling_interval (char * buff, int len, void * data)
 {
 	return snprintf(buff, len, "%i", conf->checkint);
@@ -2599,6 +2662,15 @@ snprint_def_reservation_key(char * buff,
 }
 
 static int
+snprint_def_retain_hwhandler_handler(char * buff, int len, void * data)
+{
+	if (conf->retain_hwhandler == RETAIN_HWHANDLER_ON)
+		return snprintf(buff, len, "yes");
+	else
+		return snprintf(buff, len, "no");
+}
+
+static int
 snprint_ble_simple (char * buff, int len, void * data)
 {
 	struct blentry * ble = (struct blentry *)data;
@@ -2662,6 +2734,7 @@ init_keywords(void)
 	install_keyword("wwids_file", &wwids_file_handler, &snprint_def_wwids_file);
 	install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
 	install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key);
+	install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler);
 	__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
 	__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
 	__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
@@ -2723,6 +2796,7 @@ init_keywords(void)
 	install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail);
 	install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss);
 	install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names);
+	install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler);
 	install_sublevel_end();
 
 	install_keyword_root("multipaths", &multipaths_handler);
Index: multipath-tools-120821/libmultipath/structs.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/structs.h
+++ multipath-tools-120821/libmultipath/structs.h
@@ -99,6 +99,12 @@ enum user_friendly_names_states {
 	USER_FRIENDLY_NAMES_ON,
 };
 
+enum retain_hwhandler_states {
+	RETAIN_HWHANDLER_UNDEF,
+	RETAIN_HWHANDLER_OFF,
+	RETAIN_HWHANDLER_ON,
+};
+
 struct scsi_idlun {
 	int dev_id;
 	int host_unique_id;
@@ -188,6 +194,7 @@ struct multipath {
 	int flush_on_last_del;
 	int attribute_flags;
 	int fast_io_fail;
+	int retain_hwhandler;
 	unsigned int dev_loss;
 	uid_t uid;
 	gid_t gid;
Index: multipath-tools-120821/libmultipath/configure.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/configure.c
+++ multipath-tools-120821/libmultipath/configure.c
@@ -76,6 +76,7 @@ setup_map (struct multipath * mpp, char
 	select_fast_io_fail(mpp);
 	select_dev_loss(mpp);
 	select_reservation_key(mpp);
+	select_retain_hwhandler(mpp);
 
 	sysfs_set_scsi_tmo(mpp);
 	/*
@@ -217,8 +218,10 @@ select_action (struct multipath * mpp, v
 			mpp->alias);
 		return;
 	}
-	if (!cmpp->selector || strncmp(cmpp->hwhandler, mpp->hwhandler,
-		    strlen(mpp->hwhandler))) {
+	if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON &&
+            (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
+	     strncmp(cmpp->hwhandler, mpp->hwhandler,
+		    strlen(mpp->hwhandler)))) {
 		mpp->action = ACT_RELOAD;
 		condlog(3, "%s: set ACT_RELOAD (hwhandler change)",
 			mpp->alias);
Index: multipath-tools-120821/libmultipath/dmparser.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/dmparser.c
+++ multipath-tools-120821/libmultipath/dmparser.c
@@ -56,6 +56,7 @@ assemble_map (struct multipath * mp, cha
 	int nr_priority_groups, initial_pg_nr;
 	char * p, * f;
 	char no_path_retry[] = "queue_if_no_path";
+	char retain_hwhandler[] = "retain_attached_hw_handler";
 	struct pathgroup * pgp;
 	struct path * pp;
 
@@ -81,6 +82,8 @@ assemble_map (struct multipath * mp, cha
 	} else {
 		add_feature(&f, no_path_retry);
 	}
+	if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON)
+		add_feature(&f, retain_hwhandler);
 
 	shift = snprintf(p, freechar, "%s %s %i %i",
 			 f, mp->hwhandler,
Index: multipath-tools-120821/libmultipath/propsel.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/propsel.c
+++ multipath-tools-120821/libmultipath/propsel.c
@@ -513,7 +513,9 @@ select_minio_bio (struct multipath * mp)
 extern int
 select_minio (struct multipath * mp)
 {
-	if (conf->dmrq)
+	unsigned int minv_dmrq[3] = {1, 1, 0};
+
+	if (VERSION_GE(conf->version, minv_dmrq))
 		return select_minio_rq(mp);
 	else
 		return select_minio_bio(mp);
@@ -674,3 +676,28 @@ select_reservation_key (struct multipath
 	return 0;
 }
 
+extern int
+select_retain_hwhandler (struct multipath * mp)
+{
+	unsigned int minv_dm_retain[3] = {1, 5, 0};
+
+	if (!VERSION_GE(conf->version, minv_dm_retain)) {
+		mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
+		condlog(3, "%s: retain_attached_hw_hander disabled (requires kernel version >= 1.5.0)", mp->alias);
+		return 0;
+	}
+
+	if (mp->hwe && mp->hwe->retain_hwhandler) {
+		mp->retain_hwhandler = mp->hwe->retain_hwhandler;
+		condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler);
+		return 0;
+	}
+	if (conf->retain_hwhandler) {
+		mp->retain_hwhandler = conf->retain_hwhandler;
+		condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler);
+		return 0;
+	}
+	mp->retain_hwhandler = 0;
+	condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler);
+	return 0;
+}
Index: multipath-tools-120821/libmultipath/propsel.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/propsel.h
+++ multipath-tools-120821/libmultipath/propsel.h
@@ -18,3 +18,4 @@ int select_gid(struct multipath *mp);
 int select_fast_io_fail(struct multipath *mp);
 int select_dev_loss(struct multipath *mp);
 int select_reservation_key(struct multipath *mp);
+int select_retain_hwhandler (struct multipath * mp);
Index: multipath-tools-120821/libmultipath/devmapper.c
===================================================================
--- multipath-tools-120821.orig/libmultipath/devmapper.c
+++ multipath-tools-120821/libmultipath/devmapper.c
@@ -98,12 +98,6 @@ dm_init(void) {
 	dm_log_init_verbose(conf ? conf->verbosity + 3 : 0);
 }
 
-#define VERSION_GE(v, minv) ( \
- (v[0] > minv[0]) || \
- ((v[0] == minv[0]) && (v[1] > minv[1])) || \
- ((v[0] == minv[0]) && (v[1] == minv[1]) && (v[2] >= minv[2])) \
-)
-
 static int
 dm_lib_prereq (void)
 {
@@ -126,7 +120,7 @@ dm_lib_prereq (void)
 	return 1;
 }
 
-static int
+int
 dm_drv_version (unsigned int * version, char * str)
 {
 	int r = 2;
@@ -135,6 +129,10 @@ dm_drv_version (unsigned int * version,
 	struct dm_versions *last_target;
 	unsigned int *v;
 
+	version[0] = 0;
+	version[1] = 0;
+	version[2] = 0;
+
 	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
 		return 1;
 
@@ -169,28 +167,6 @@ out:
 	return r;
 }
 
-int
-dm_drv_get_rq (void)
-{
-	unsigned int minv_dmrq[3] = {1, 1, 0};
-	unsigned int version[3] = {0, 0, 0};
-        unsigned int * v = version;
-
-	if (dm_drv_version(v, TGT_MPATH)) {
-		/* in doubt return least capable */
-		return 0;
-	}
-
-	/* test request based multipath capability */
-	if VERSION_GE(v, minv_dmrq) {
-		condlog(3, "activate request-based multipathing mode "
-			   "(driver >= v%u.%u.%u)",
-			minv_dmrq[0], minv_dmrq[1], minv_dmrq[2]);
-		return 1;
-	}
-	return 0;
-}
-
 static int
 dm_drv_prereq (void)
 {
Index: multipath-tools-120821/libmultipath/devmapper.h
===================================================================
--- multipath-tools-120821.orig/libmultipath/devmapper.h
+++ multipath-tools-120821/libmultipath/devmapper.h
@@ -8,7 +8,7 @@
 
 void dm_init(void);
 int dm_prereq (void);
-int dm_drv_get_rq (void);
+int dm_drv_version (unsigned int * version, char * str);
 int dm_simplecmd_flush (int, const char *, int);
 int dm_simplecmd_noflush (int, const char *);
 int dm_addmap_create (struct multipath *mpp, char *params);
@@ -46,4 +46,10 @@ int dm_setgeometry(struct multipath *mpp
 void udev_wait(unsigned int c);
 void udev_set_sync_support(int c);
 
+#define VERSION_GE(v, minv) ( \
+ (v[0] > minv[0]) || \
+ ((v[0] == minv[0]) && (v[1] > minv[1])) || \
+ ((v[0] == minv[0]) && (v[1] == minv[1]) && (v[2] >= minv[2])) \
+)
+
 #endif /* _DEVMAPPER_H */




More information about the dm-devel mailing list